- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 React 16.8.2,每当应用程序组件中的状态发生更改时,我都会遇到组件卸载的问题。
这是场景:
我的问题:当 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/
1.使用start-all.sh启动hadoop服务时,提示输入 您确定要继续连接吗(是/否) 当我通过脚本启动它时如何抑制这个提示,现在我正在使用期望模块,但我认为可能有一种更简单的方法来做到这一点
我安装了在 Ubuntu 12.04 下运行的 Geonode R 2.01。我尝试使用以下命令卸载它: sudo apt-get remove --purge geonode sudo apt-ge
假设我有 AppDomainA,它启动 AppDomainB。 AppDomainB 然后启动 AppDomainC。 如果在 AppDomainA 中卸载 AppDomainB,AppDomainC
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
我尝试使用以下命令从我的 Ubuntu 中卸载 NGinX: sudo apt-get remove nginx-core nginx-full nginx-light nginx-extras n
我已经从 /Applications/ 中删除了 MacVim目录,但当我输入 vim 时在终端中显示错误:no such file or directory: /Applications/MacVi
我的页面中有一个 iframe,该 iframe 嵌入了一个不在我的服务器上的网站。 我正在寻找一种在 iframe 重定向之前触发函数的方法。例如,当用户单击 iframe 内的链接并且 ifram
看来我被 Visual Studio 的 Atomineer Pro 文档加载项挟持了!试用期结束了,我没有用了!但现在每次我在 Visual Studio 中做某事时,我都会收到一条错误消息并发送到
我有一个使用 WiX 完成的安装程序。安装完成后,它会启动一个应用程序,在 Explorer 进程中注入(inject)一些代码。 目前,当我卸载时,重新启动管理器会启动并关闭我的应用程序和资源管理器
在我的网络应用中,我需要在用户离开页面之前发送他们更改的最新数据。 我在页面卸载时调用这样的函数: window.onbeforeunload=sendData; 这就是函数内部调用的内容 funct
我使用 jQuery 和 history.js 来管理部分页面之间的动态转换;这样我就可以避免重新加载整个文档。其中一些部分页面调用自己独特的 javascript 文件。虽然页面之间的转换运行良好,
我需要处理应用程序包的变化,我这样写我的 mainfest mainfest.xml 我的接收器类
我目前在使用大量内存方面遇到了麻烦,我正在尽一切努力削减和优化涉及内存的代码...目前我的游戏的大部分 Nib 文件都加载了所有它在 ViewDidLoad 中的变量,现在我的问题是,在我的 view
如何从系统中删除 composer Php Dependecny Manager? 它说卸载无法继续,因为以下应用程序正在使用需要删除的文件。 Windows 资源管理器 最佳答案 我遇到了同样的问题
所以我使用 stow 在服务器上安装了 Python 2.7.1 源代码 .我过去很粗心,在处理源代码安装时我试图保持井井有条。所以,输入 stow。现在我使用 wget 安装了 easy_insta
有谁知道如何卸载 MacRuby?我在使用 RubyCocoa 然后决定试用 MacRuby,在安装 MacRuby 之后,RubyCocoa 已经停止工作。所以我想删除 MacRuby,但我找不到任
我无法从 64 位 EC2 卸载 mongo。在/usr/bin 我有 mongo 和 mongod 等等。当我从任何地方键入 mongo 时,它会在 1.8 版打开 shell。我现在下载了 2.0
本文实例讲述了Android编程实现监控apk安装,卸载,替换的方法。分享给大家供大家参考,具体如下: ?
1说明 mysql++是mysql开发团队为OO编程提供的C++开发库,是对mysql提供的底层数据存取API进行的C++封装,用其手册上的说法是:复杂而又庞大,当然功能也更强大。 Mysql+
自从我开始建立我的网站那天起,我安装了很多包,有时是为了测试一堆代码,有时是为了项目本身(后来我发现这不是需要的包)。但是现在,当我运行 pip freeze 时,我有一个包列表,我很难卸载不使用的包
我是一名优秀的程序员,十分优秀!