reactjs - 当 react 执行 componentDidMount 和 componentWillUnmount
问题描述
我用 React 玩了几年,在某些情况下仍然对挂载/卸载机制感到困惑。
由于挂载/卸载是执行副作用的地方,我不希望它们被随机调用。所以我需要弄清楚它们是如何工作的。据我目前所知,当虚拟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);
组件一是 remount 超时应用程序渲染而组件二不是?为什么会发生这种情况?
解决方案
Component
每次App
渲染都是一个新功能,所以<Component name="one" />
每次都重新安装,它们被认为是不同的组件。
Component("two")
call的结果是<TestMount name={"two"} />
,TestMount
每次App
渲染都保持不变,所以不会重新挂载。
Component
对于它的用途来说是无效的组件,将name
字符串作为name
prop 传递给TestMount
组件,因为name
参数不是字符串,而是 props 对象,当Component
使用<Component name="one" />
. name => <TestMount name={name} />
是render function,为了清楚起见,最好将其命名为 like renderTestMount
,因为不应该直接调用组件 like Component("two")
。
如果一个函数应该作为组件或渲染函数互换使用,则签名应更改为({ name }) => <TestMount name={name} />
.
<Component name="one" />
通过 memoizing可以实现预期的行为Component
:
const Component = useCallback(({ name }) => <TestMount name={name} />, []);
但由于Component
不依赖于App
范围,正确的方法是在外部定义它:
const Component = ({ name }) => <TestMount name={name} />;
function App() {...}
例如,这就是 React Router为组件和渲染函数Route
单独设置component
和render
props的原因。这允许防止对需要在当前范围内动态定义的路由组件进行不必要的重新安装。
推荐阅读
- python - ValueError:没有足够的值来解包(预期 4,得到 3)
- javascript - HTML、CSS、JS:使用按钮和事件监听器猜测游戏网页:提示和重置按钮不起作用
- python - 在 Cython 中附加 C 数组(或任何数组)的最佳方法
- python - Groupby 按日期排序,根据其他列值找到最小值、最大值
- maven - 将 artifactId 传递给 surefire argLine
- r - 一次导入多个 .tsv 文件作为数据框
- scala - Scala:将用户输入读取为单个字符串
- python - 如何重定向以使用新上下文而不是 django 的原始上下文?
- html - 如何为有序列表编号做css样式?
- swift - Swift 撤消功能,之前声明的变量始终为空