从 Child 更新父项状态,而不触发 React 中 Child 的重新渲染



所以我正在尝试在 react 中构建一个单页应用程序。

我想要的:在页面上,您可以像往常一样访问不同的页面。在一个页面(索引(上,我想要一个用户可以单击的按钮,该按钮将另一个组件展开到带有表单的视图中。展开后,此组件或窗体应在所有页面上可见。

问题:索引页从 API 加载一些数据,因此当索引组件挂载时,会进行获取调用。但是当用户单击"展开表单"按钮时,父组件的状态会按预期更新,但子组件会重新呈现,这会导致索引组件再次获取数据,这不是我想要的。

我尝试了什么

// Parent Component
const App => props => {
const [composer, setComposer] = useState({
// ...
expanded: false,
});
const expandComposer = event => {
event.preventDefault();
setComposer({
...composer,
expanded: true
});
return(
// ...
<Switch>
// ...
<Route
exact path={'/'}
component={() => (<Index onButtonClick={expandComposer}/>)}
// ....
{composer.expanded && (
<Composer/>
)};
);
};
// Index Component
const Index=> props => {
const [isLoading, setIsLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(()=> {
// load some data
}, []);
if(isLoading) {
// show spinner
} else {
return (
// ...
<button onClick={props.onButtonClick}>Expand Composer</button>
// ...
);
};
};

因此,使用我的方法,单击按钮时,索引组件会再次获取数据,并且微调器在短时间内可见。但我不想重新挂载索引,或者如果可能的话至少重新加载数据

这里有两个问题。首先,默认情况下,React将在父组件更新时重新呈现所有子组件。若要避免此行为,应显式定义组件应更新的时间。在基于类的组件中,PureComponentshouldComponentUpdate是要走的路,而在功能组件中,React.memo等同于PureComponent。仅当其中一个PureComponent发生props更改时,才会更新。所以你可以像这样实现它:

const Index = () =>{/**/}
export default React.memo(Index)

但这不会解决您的问题,因为第二个问题。PureComponentReact.memoprops中执行shallow comparison,并且您正在传递一个内联函数作为prop,它将在每个shallow comparison中返回false,因为每次渲染都会创建一个函数的新实例。

<Child onClick={() => this.onClick('some param')} />

这实际上会在每次渲染时创建一个新函数,导致比较始终返回false。解决方法是将参数作为第二个prop传递,如下所示

<Child onClick={this.onClick} param='some param' />

在里面Child

<button onClick={() => props.onClick(props.param)} />

现在,您没有在渲染上创建任何函数,只是将this.onClick的引用传递给您的孩子。

我不完全熟悉你的 React 风格,我不使用它们特殊的状态函数。

为什么不在父状态中添加一个布尔值,称为"fetched"。

if (!fetched(fetch(params, ((=>setState({ fetched: true ((;

希望这有帮助

愚蠢的我,我在定义路由时使用了component={() => ...}而不是render={() => ...}。如 react router 文档中所述,使用component始终会重新渲染组件。杜波卡斯的答案现在非常有效:)

最新更新