当道具改变时,重新渲染反应成分

Dav*_*vid 59 reactjs redux react-redux

我正在尝试将表示组件与容器组件分开.我有一个SitesTable和一个SitesTableContainer.容器负责触发redux操作以基于当前用户获取适当的站点.问题是在最初呈现容器组件之后,异步获取当前用户.这意味着容器组件不知道它需要在其componentDidMount函数中重新执行代码,这将更新要发送给的数据SitesTable.我想我需要在其中一个props(用户)更改时重新呈现容器组件.我该怎么做?

class SitesTableContainer extends React.Component {
    static get propTypes() {
      return {
        sites: React.PropTypes.object,
        user: React.PropTypes.object,
        isManager: React.PropTypes.boolean
      }
     }

    componentDidMount() {
      if (this.props.isManager) {
        this.props.dispatch(actions.fetchAllSites())
      } else {
        const currentUserId = this.props.user.get('id')
        this.props.dispatch(actions.fetchUsersSites(currentUserId))
      }  
    }

    render() {
      return <SitesTable sites={this.props.sites}/>
    }
}

function mapStateToProps(state) {
  const user = userUtils.getCurrentUser(state)

  return {
    sites: state.get('sites'),
    user,
    isManager: userUtils.isManager(user)
  }
}

export default connect(mapStateToProps)(SitesTableContainer);
Run Code Online (Sandbox Code Playgroud)

QoP*_*QoP 78

您必须在componentDidUpdate方法中添加条件.

这就是组件的外观

import equal from 'fast-deep-equal'

...

constructor(){
  this.updateUser = this.updateUser.bind(this);
}  

componentDidMount() {
  this.updateUser();
}

componentDidUpdate(prevProps) {
  if(!equal(this.props.user, prevProps.user)) // Check if it's a new user, you can also use some unique property, like the ID  (this.props.user.id !== prevProps.user.id)
  {
    this.updateUser();
  }
} 

updateUser() {
  if (this.props.isManager) {
    this.props.dispatch(actions.fetchAllSites())
  } else {
    const currentUserId = this.props.user.get('id')
    this.props.dispatch(actions.fetchUsersSites(currentUserId))
  }  
}
Run Code Online (Sandbox Code Playgroud)

更新(React 17)

看起来fast-deep-equal将在React 17中删除.您可以使用useDeepCompareEffect而不是useEffect实现相同的事情.

新示例使用componentDidUpdate而不是fast-deep-equal比较对象.

import React, { useEffect } from 'react';

const SitesTableContainer = ({
  user,
  isManager,
  dispatch,
  sites,
}) => {
  useEffect(() => {
    if(isManager) {
      dispatch(actions.fetchAllSites())
    } else {
      const currentUserId = user.get('id')
      dispatch(actions.fetchUsersSites(currentUserId))
    }
  }, [user]); 

  return (
    return <SitesTable sites={sites}/>
  )

}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,componentWillReceiveProps生命周期方法已被弃用,可能会在React 17中删除。React开发团队建议使用componentDidUpdate和新的getDerivedStateFromProps方法的组合。在他们的博客文章中有更多信息:https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html (4认同)

小智 21

您可以使用KEY随道具更改的唯一键(数据的组合),并且该组件将使用更新的道具重新呈现。


ob1*_*ob1 15

ComponentWillReceiveProps()由于错误和不一致,将来会被弃用.在道具改变上重新渲染组件的替代解决方案是使用ComponentDidUpdate()ShouldComponentUpdate().

ComponentDidUpdate()每当组件更新时调用,如果ShouldComponentUpdate()返回true ,则调用(如果ShouldComponentUpdate()未定义,则true默认返回).

shouldComponentUpdate(nextProps){
    return nextProps.changedProp !== this.state.changedProp;
}

componentDidUpdate(props){
    // Desired operations: ex setting state
}
Run Code Online (Sandbox Code Playgroud)

ComponentDidUpdate()通过在其中包含条件语句,仅使用该方法可以实现相同的行为.

componentDidUpdate(prevProps){
    if(prevProps.changedProp !== this.props.changedProp){
        this.setState({          
            changedProp: this.props.changedProp
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

如果试图在没有条件的情况下设置状态或者没有定义ShouldComponentUpdate()组件将无限重新渲染

  • 由于`componentWillReceiveProps`即将被弃用,并且建议不要使用,因此需要对该答案进行投票(至少目前是这样)。 (4认同)

mr.*_*r.b 5

componentWillReceiveProps(nextProps) { // your code here}
Run Code Online (Sandbox Code Playgroud)

我认为这是你需要的事件.componentWillReceiveProps当您的组件通过道具收到某些内容时触发 从那里你可以检查然后做你想做的事.

  • `componentWillReceiveProps`已弃用* (5认同)