gpt4 book ai didi

reactjs - 当父状态改变时组件卸载

转载 作者:行者123 更新时间:2023-12-03 13:35:18 26 4
gpt4 key购买 nike

我正在使用 React 16.8.2,每当应用程序组件中的状态发生更改时,我都会遇到组件卸载的问题。

这是场景:

  • 我有 App.jsx(一个功能组件)和许多状态变量 (useState)
  • 其中一些状态变量的 setter 通过 Context 提供程序(后代中的 useContext)沿树向下传递
  • 我有一个菜单组件(应用程序的后代),它调用这些 setter 来(例如)显示模式对话框
  • 我有一个模式对话框组件(App 的子组件),它使用状态变量作为属性来确定它是否打开——我认为这是标准的 React 东西。

我的问题:当 App 中的任何状态变量发生更改(当然是通过钩子(Hook))时,App 的子级将被卸载并重新安装 - 即使它们与正在更改的状态没有任何连接。它们不仅仅是重新渲染 - 子级被卸载并且它们的状态被重新初始化。因此,例如,我的对话框中的字段在不应该被清除的情况下被清除了。

这已经是一个相当复杂的应用程序,所以我今天花了很多时间来隔离问题。然后,我设置了一个简单的 create-react-app 来尝试在那里复制此行为 - 但此测试应用程序的行为就像它应该的那样。更改父状态,无论是通过 prop 回调,还是通过子级上下文提供的回调 - 重新渲染,但不会卸载/重新安装,并且子状态保持不变。

但在我的真实应用程序中,组件重新安装并且子状态重新初始化。

我已经将其简化到了我能做到的最简单的程度 - 我通过子级的上下文设置了一个假状态变量“foo”和“setFoo”。即使 foo 未被任何组件使用,更改 foo 的值也会导致 App 的子组件卸载/重新安装。

在 App.jsx 中:

const App = props => {
const [foo, setFoo] = useState(false);
// ...
const appControl = {
toggleFoo: () => setFoo(!foo);
};
// ...
return (
<AppContext.Provider value={appControl}>
... a bunch of stuff not using foo anywhere
... including, deep down:
<Menu />
</AppContext.Provider>
);
};

在 Menu.jsx 中:

const Menu = props => {
const appControl = useContext(AppContext);
// ...
return (
... super simplified for test
<div onClick={appControl.toggleFoo}>
Toggle Foo
</div>
);
};

如果我正确理解状态,我确实相信更改状态应该导致子项被重新渲染,但不会重新安装。这是我在简单的 create-react-app 测试中看到的,但不是在我的真实应用程序中看到的。

我确实发现我没有使用最新的 React - 也许升级可以解决这个问题?

感谢您对我可能做错的地方或误解的任何见解。

最佳答案

已解决。这是一件有趣的事。这就是发生的事情。

在我的应用程序组件中,我有一个相当深的 HOC 树。由于我做出了一些可疑的决定,我最终将应用程序分成了两个组件。应用程序和应用程序核心。我这样做是有原因的,而且在凌晨 3 点似乎是有道理的。但为了既快又脏,我将 AppCore 作为 const 固定在我的 App 函数中。我记得自己心里想:“我想知道这会导致什么问题?”现在我明白了。也许 React 专家可以向我充分解释这一点,因为我没有看到 JSX 分配给常量和 JSX 直接返回之间的区别。但显然是存在的,而且这很容易重现。

要重现,请 create-react-app 一个测试应用程序:

create-react-app test
cd test

然后将 App.js 的内容替换为:

import React, { useState, useEffect } from "react";

const Menu = props => <div onClick={props.click}>Toggle Foo</div>;

const Test = props => {
useEffect(() => {
console.log("mounted");
return () => console.log("unmounted");
}, []);
return null;
};

const App = props => {
const [foo, setFoo] = useState(false);

// this is the root of the problem
// move this line outside of the function body
// and it mounts/unmounts correctly
const AppCore = props => <Test />;

return (
<>
<Menu click={() => setFoo(!foo)} />
<AppCore />
</>
);
};

export default App;

然后 npm start,当您单击“Toggle Foo”时,您将看到测试组件已卸载/重新安装。

这里的解决方案是将 AppCore 移出函数体。在我真正的应用程序中,这意味着我需要进行一些重构。

我想知道这是否会被视为 React 问题?

关于reactjs - 当父状态改变时组件卸载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55606873/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com