首页 > 解决方案 > 状态更改不重新渲染组件

问题描述

我无法在任何地方找到答案,因为没有什么对我有用,所以我开始了一个新话题。请不要将其标记为重复


路由器.js:

<Switch>
   <Route path="/" exact component={Home} />
   <Route exact path="/p/:uid" component={Profile} />
</Switch>

Profile.js

constructor(props) {
  super(props);
  this.state = {
    loading: true,
    profile_user_id: this.props.match.params.uid,
  };
}

然后,稍后在 Profile.js 中,我触发 fetch 从后端获取数据并使用 this.setState({ ... }) 将此数据保存到 state。当 Profile 组件被渲染时,一切看起来都很好。

在Router.js中,还有一个Link:

<Link to={"/p/" + this.state.ntuser.tag}>Profile</Link>

..这应该去你自己的个人资料。因此,当您的用户 ID 为 1,并且您访问 id 为 22 的用户的个人资料时,您的 URL 将是 /p/user22,并且链接将指向 /p/user1。

问题是,即使配置文件渲染得很好,当您单击链接时,配置文件组件也不会重新呈现(这应该将您定向到 /p/user1 并显示您的配置文件)。我也尝试将位置从 react-router 保存到状态,因此每次 URL 更改时,它都会在 componentWillReceiveProps() 中捕获并在内部更新状态。但还是一无所获。有任何想法吗?

PS:我正在使用 React.Component

标签: reactjsreact-router

解决方案


console.log(this.props.match.params.uid)constructor,componentDidMount()componentDidUpdate()(UNSAFE_componentWillReceiveProps()已弃用)

(日志调用的)数量和位置将告诉您组件是重新创建(许多构造调用)还是更新(cDM 调用)。相应地移动您的数据获取调用(进入 cDM 或 cDU ...或 sCU)。

您可以在上面的组件中保存公共数据<Router/>(fe 使用上下文 api) - 但在这种情况下不需要这样做。


解决方案

您可以使用 componentDidUpdate() 或 shouldComponentUpdate()从更改的道具更新状态。componentDidUpdate应有条件保护以防止无限循环。请参阅文档

最简单的解决方案:

componentDidUpdate(prevProps) {
    if (this.props.some_var !== prevProps.some_var) {
        // prop (f.e. route '.props.match.params.uid') changed
        // setState() - f.e. for 'loading' conditional rendering
        // call api - use setState to save fetched data
        // and clearing 'loading' flag 
    }
}

shouldComponentUpdate()可用于一些优化 - 最小化重新渲染。


推荐阅读