我具有以下组件结构:
主要路线:
<div>
<Header />
<Switch>
<Route exact path="/" render={() => <Home />} />
<Route path="/category" render={() => <Categories />} />
<Route path="/products" render={() => <Products />} />
</Switch>
</div>
产品路线:
const productsData = [...];
return (
<div>
<div>
<ProductList data={productsData} />
</div>
<Switch>
<Route path={`${match.url}/:productId`} render={()=>
<ProductDetail data={productsData} />} />
<Route exact path={match.url} render={()=> (
<div style={{ textAlign: "center" }}>Select a product.</div>
)} />
</Switch>
</div>
);
以及ProductDetail中的路线:
return (
<>
<div>
<h3> {product.name} </h3>
Links:
<div>
<NavLink activeClassName="active" to={`${match.url}/detail/${ "100"}`}>
Click me
</NavLink>
</div>
</div>
<div>
<Route path={`${match.url}/detail/:code`} render={()=>
<ProductDetailMore />} />
</div>
</> );
当我单击“单击我”时, 100 值会正确显示在我的 ProductDetailMore 组件中,但所有组件都将重新呈现(产品,ProductList,ProductDetail, ProductDetailMore);因此,我的问题是,如何防止父组件[Products,ProductDetail]中的重新渲染?
尤其是,我想避免在ProductList中重新渲染,而不是在Route中?
答案 0 :(得分:1)
您通常不能真正避免重新渲染,因为react已经决定了哪些组件需要重新渲染。但是,这仅意味着您无法避免重新渲染父组件。使用react dev工具,您可以分析它们为什么要重新渲染(在探查器中是一个选项),并可能找到不必要的原因来重新渲染。
但这是个好消息:
您可以轻松地进行操作,以防止子组件重新渲染。例如“ ProductList”。一种方法是将React.memo HOC直接用于组件的导出或“类别”组件(在静态位置,而不是在render函数中):
const ProductListMemo = React.memo(ProductList)
然后,您在渲染函数中使用“ ProductListMemo”。这样,在渲染组件时,React会预先检查是否有任何道具更改。如果不是,则不重新渲染组件。您的代码虽然不完整。您定义
const productsData = [...]
如果这是在render函数中,则将始终创建一个新数组,即使内容相同,React.memo也将看到一个新数组并重新渲染组件。您必须将数组移到render函数之外,或者必须将其包装在useMemo中(如果您不使用类组件):
const productsData = useMemo(() => [...], []);
这个“ useMemo”钩子也可以用来避免组件的重新渲染,可以使用
{useMemo(() => (<div>
<ProductList data={productsData} />
</div>), [productsData])}
这样,每个重新渲染的反应都会检查“ productsData”是否发生了更改,然后才重新渲染组件。
所以要知道的重要一点是,例如,如果父组件由于状态更新而重新渲染,它将重新渲染每个子组件。这些也将重新渲染其所有子组件。但是,通过React.memo或useMemo,您可以帮助做出反应,以决定使用以前渲染的组件。