我在React玩了几年,在某些情况下仍然对mount / unmount机制感到困惑。
由于安装/卸载是执行副作用的地方,因此我不希望它们被随机调用。所以我需要弄清楚它们是如何工作的。据我目前所了解,当虚拟dom不存在于实际dom中时,往往会被卸载。但是,这似乎不是全部,我无法对此进行推理
function TestMount(props) {
useEffect(() => {
console.log("componentDidMount", props.name);
return () => {
console.log("componentWillUnount", props.name);
};
}, []);
return <h1>Test content {" " + JSON.stringify(props.name)}</h1>;
}
function Update({ click }) {
return <button onClick={click}>Update</button>;
}
function App() {
const [count, setCount] = useState(0);
const Component = name => <TestMount name={name} />;
return (
<div className="App">
<h1>{count}</h1>
<Component name="one" />
{Component("two")}
<Update click={() => setCount(x => x + 1)} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Run Code Online (Sandbox Code Playgroud)
组件一需要重新安装应用程序渲染,而组件二却没有?为什么会这样?
Component是每次App渲染时的新功能,因此<Component name="one" />每次也都重新安装,它们被视为不同的组件。
Component("two")调用的结果是<TestMount name={"two"} />,TestMount每次App呈现时都保持不变,因此不会重新安装。
Component无效,因为它的用途是将name字符串作为nameprop 传递给TestMountcomponent,因为name在Component使用like 时参数不是字符串而是props对象<Component name="one" />。name => <TestMount name={name} />是render函数,因此renderTestMount为了清楚起见,最好相应地命名它,因为不应将组件直接调用为like Component("two")。
如果假定功能可以互换地用作组件或呈现功能,则应将签名更改为({ name }) => <TestMount name={name} />。
对于能否实现预期的行为<Component name="one" />由memoizing Component:
const Component = useCallback(({ name }) => <TestMount name={name} />, []);
Run Code Online (Sandbox Code Playgroud)
但是由于Component不依赖于App范围,所以正确的方法是在外部进行定义:
const Component = ({ name }) => <TestMount name={name} />;
function App() {...}
Run Code Online (Sandbox Code Playgroud)
举例来说,这是原因阵营路由器Route有独立的component和render为组件道具和呈现功能。这样可以防止不必要地重新安装需要在当前范围内动态定义的路由组件。
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |