React-router 改变 params 时组件如何重新挂载

#1

最近使用 react-router 来做单页面路由,现在遇到一个问题,就是对于同样的路由(不同的参数),指向同一个组件,改变参数的情况下,该组件不能卸载和重新挂载,功能效果类似于在用户a的主页(/users/1/overview),点击进入用户b的主页(/users/2/overview),这时候,组件没有被卸载。

// 路由配置
<Route path='/' component={App}>
  <Route path='users/:userId/overview' component={User} />
</Route>
// 用户组件
export class User extends Component {
  constructor() {
    this.state = {
      profile: {},
      firends: [],
    };
  }
  componentDidMount() {
    const { userId } = this.props.params.userId;
    this.loadProfile(userId);
    this.loadFirends(userId);
  }
  shouldComponentUpdate(nextProps, nextState) {
    console.log(nextProps.params.userId);// 修改url进入的,这里能正确获取到新用户id
    return true;
  }

  loadProfile(userId) {
    fetch();// 请求数据,更新state
  }
  loadFirends(userId) {
    fetch();// 请求数据,更新state
  }

  render() {
    const { profile, firends } = this.state;

    return (
    <div>
      <div>profile data</div>
      <div>firends data</div>
    </div>
    );
  }
}

当我点击 /users/1/overview 进入用户a主页后,我修改浏览器地址为 /users/2/overview 回车(或者,我点击用户a界面上的 Link 标签进入 /users/2/overview),这个时候,url是改变了,在 shouldComponentUpdate 函数中也能正确获取用户id,这个时候我如何巧妙的处理当前组件重新加载数据这个过程,我知道可以在 shouldComponentUpdate 函数中获取新的用户id来和 this.props.params.userId 做对比,不同则重新加载数据,但是我又很多这种组件啊,很多这种跳转,是不是我每一个组件都要这么处理啊,感觉要疯了。。而且,在复杂的页面里面,有可能在组件挂载的时候,我需要发送很多个请求,难道我在 componentDidMount 函数内部所做的处理也要在 shouldComponentUpdate 里面再来一次吗?

react-router 相关的资料我也看了七七八八,难免有遗漏的部分,还是很困惑,不知道如何解决类似的问题,所以才来提问,希望知道的朋友说说自己的解决方法,先谢谢了。

[干货]React-Keeper : 比React-Router更适合你的单页面路由器
#2
componentWillReceiveProps(nextProps) {}
#3

首先,谢谢您的回复。

componentWillReceiveProps(object nextProps)

在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用。
用此函数可以作为 react 在 prop 传入之后, render() 渲染之前更新 state 的机会。老的 props 可以通过 this.props 获取到。在该函数中调用 this.setState() 将不会引起第二次渲染。

在这里处理 nextProps 的问题会比在 shouldComponentUpdate 处理更加方便,但是没有解决我数据加载逻辑分部在 componentDidMount其它地方的问题。

再次感谢您提供的解决思路。

#4

我是这样处理的:

chkProps(props){
	// do some thing
},
componentWillMount() {
	this.chkProps(this.props)
},
componentWillReceiveProps(nextProps) {
    this.chkProps(nextProps)
},
#5

恩恩,我也想到了这样的处理方式, :smile:
我在想,有没有方法在这种类型的url change时,让当前组件依次调用 componentWillUnmount componentDidMount ,也就是让当前组件重新挂载,这样的话,我们给组件写的业务逻辑就不需要再封装了啊,不知道有没有这样的方式。

#6

这个不会调用的,我也遇到类似的问题,我是让他先跳出到另一个router然后在跳回来。 效果是实现了,但是屏幕会闪烁一下。 这个闪烁可以通过增加一些过度动画来解决掉。

#7

好的,谢谢您,我去尝试一下。
还是希望能有一个更好的实现方式,能够做到url中的参数改变能够重新挂载组件。

#8

我目前是reset组件的数据,然后调用componentDidMount

#9

试试location.assign(’/user/1’)

1 Like
#10

我也遇到这个问题了。
采用了很多人推荐的:componentWillReceiveProps(nextProps) {}方法

关注下,这个需求确实很常见

#11

参考此文 React 有状态组件及 key 属性的应用

1 Like
#12

感谢您的答案!非常有用,谢谢!

#13

可以用redux试试,处理异步请求很方便

#14

这一个怎么更新子页面的state

#15

params映射为组件的key就行啦

#16

componentWillReceiveProps(nextProps)这个可以欸
谢谢

#17

不过如果再次刷新就没有了
如果另外加上componentwillmount的话刷新也是可以的

#18
static getDerivedStateFromProps(props, state) {
    // 在这里做一下可以做一下state的初始化
}