[英]React - Rerender on props change / dynamically changing css without rerender
我需要在显示/隐藏导航时隐藏 React 应用程序上的页面内容。
为此,我们将 prop 传递给组件,并在样式组件中处理显示 css,如下所示:
<PageContent isOpen={isOpen}>
const PageContent = styled.div`
display: ${props => (props.isOpen ? 'none' : 'block')};
`;
虽然这可以正常工作,但当道具更改时,内部页面内容会重新呈现,这是预期但不希望的。
在这种情况下,页面内容包括从 API 获取的一些内容,因此每次打开/关闭导航时,我们都会再次呈现内容并再次从 API 获取,这是不需要的。
有没有办法动态控制隐藏/显示主要内容持有者,而无需每次都重新渲染? 还是我们应该更多地研究执行获取而不是更新的组件?
将组件 css 更改为显示隐藏应该只会在视觉上隐藏它,但组件仍应安装在 DOM 树上。
也许您的 API 提取在每次重新渲染时都会发生,而应该只在组件安装时发生。
正是这是一个预期的行为,你可以做的不是使用 CSS 隐藏组件,而是返回并清空片段,如果“isOpen”为真,防止 API 调用,如果这些调用来自内部组件
<>
</>
如果可能的话
我最终将不关心父道具的主要内容包装在PureComponent
中。
React 的 PureComponent 对组件的 props 和 state 进行了浅层比较。 如果没有任何改变,它会阻止组件的重新呈现。 如果发生了变化,它会重新渲染组件。
每当一个组件触发 state 时,它的所有子组件都会重新渲染,即使子组件没有中继该 state。 要解决此问题,您需要使用React.memo
为功能组件包装子组件,或为 class 组件使用PureComponent
。 这将检查道具更改并重新渲染孩子。
这里有一个组件在安装时获取数据的示例,并且有一个按钮,在click
时触发 state: 代码
import React, { useState, useEffect } from "react";
import "./styles.css";
import MyData from "./MyData";
const fakePromise = () =>
new Promise((resolve) => {
setTimeout(() => {
resolve("data returned");
}, 2000);
});
export default function App() {
const [hidden, setHidden] = useState(false);
const [data, setData] = useState();
useEffect(() => {
const fetchData = async () => {
try {
const data = await fakePromise();
setData(data);
} catch (error) {
throw error;
}
};
fetchData();
}, []);
return (
<div className="App">
<div style={{ display: hidden ? "none" : "block" }}>I am visible</div>
<button onClick={() => setHidden(!hidden)}>Toggle Visiblity</button>
{data && <MyData data={data} />}
</div>
);
}
在示例中,您可以看到MyData
组件不会在隐藏的 state 上中继,但如果我们没有将其包装在React.memo
中,它将重新渲染。
MyData.js
import React from "react";
const MyData = ({ data }) => {
console.log("render");
return (
<div>
<h1>{data}</h1>
</div>
);
};
//export default MyData;
export default React.memo(MyData);
注意: React.memo
比较当前道具和下一个道具,如果其中一些道具是 function 或 static 数据array/object
,每次组件重新渲染时,这些将被重新创建,这将重新渲染孩子,所以你需要记住这些道具使用诸如useCallback
或useMemo
类的钩子。
谢谢希望这能回答你的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.