在这里,我在父组件中创建了一个重新渲染的切换按钮,在子组件中创建了一个加号按钮,计数器要求是切换按钮重新渲染是一个将隐藏和显示组件的切换按钮,但如果有最后一个计数器添加,例如从0到2,隐藏和显示后它应该保持不变,就像2而不是0,但问题是我无法隐藏子组件,那么我该如何隐藏和显示子组件并维护子状态?基本上,通过渲染父级,我想继续维护子级状态值。父代码是
import React, { useRef, useState, useMemo } from 'react';
import DropDown from './DropDown';
function App() {
const shouldRenderChild = useRef(true);
const [hide, setHide] = useState(false);
const toggleChildRendering = () => {
shouldRenderChild.current = !shouldRenderChild.current;
setHide(!hide);
};
const MemoizedDropDown = useMemo(() => {
return shouldRenderChild.current ? <DropDown /> : null;
}, []);
return (
<div>
<button onClick={toggleChildRendering}>
Toggle Child Rendering
</button>
{MemoizedDropDown}
</div>
);
}
export default App;
子代码是
import React, { useState } from "react";
export default function DropDown() {
const [number, setNumber] = useState(0);
return (
<>
<button onClick={() => setNumber(number + 1)}>+</button>
<div>Child Component{number}</div>
</>
);
}
每次安装或卸载组件(使用条件渲染)时,组件的状态都会将自身重新设置为默认值。所以这就是你的问题,
useMemo
hook 在这里帮不了你。要解决您的问题,您可以修改根 css 文件并添加类似类的
.hidden
内容:很可能您的项目中已经有了这种实用程序类。就像
d-none
引导程序或类似的。接下来 - 您需要向
DropDown
组件添加一个包装器,或者将该组件返回的根节点的类型更改为React.Fragment
ie以外的其他类型<> </>
,并对其应用条件,className
如下所示:这是解决方案的示例:
Stackblitz演示
您的方法的主要问题是您使用的
useMemo
方式错误。useMemo
缓存计算值(在本例中为组件),并且仅在其依赖项之一发生更改时才会重新计算该值。您应该使用useMemo
来决定是否渲染DropDown
组件,并作为该决定的依赖项,使用hide
.这是更详细的解决方案:
父组件: 我们将使用
hide
状态来确定是否应该显示子组件。我们将用来useMemo
缓存子组件。如果hide
发生变化,则会重新计算是否显示子组件。子组件: 这保持不变。它只是显示一个增加计数器的按钮。
通过遵循这种方法,您可以显示/隐藏子组件,而不会丢失其内部状态。但是,请注意,如果子组件被卸载(即从 DOM 中完全删除)然后重新安装,其内部状态将被重置。如果即使组件已卸载也想保留状态,则需要更复杂的解决方案,例如使用上下文或将状态向上移动到父组件并将其作为 props 向下传递。
解决这个问题的简单方法是提升国家地位。
!hide ? <DropDown /> : null
时它将被卸载。hide
number
儿童状态时,它也会消失。number
值存储在父级的状态中,它就会持续存在。hide
标志为 true 而被卸载,您仍然可以将状态保存在 Parent 中。hide
标志来设置子组件的样式display: none
<下拉样式={{显示:隐藏?'无' : '阻止' }} ... />
正确的方式:
应用程序.js
Dropdown.js