【问题标题】:infinite loop when dispatching in componentWillReceiveProps在 componentWillReceiveProps 中调度时的无限循环
【发布时间】:2016-07-11 10:17:40
【问题描述】:

我有一个由 react-router (path="profile/:username") 加载的 Profile 组件,该组件本身如下所示:

...
import { fetchUser } from '../actions/user';

class Profile extends Component {
  constructor(props) {
    super(props);
  }
  componentDidMount() {
    const { username } = this.props;
    this.fetchUser(username);
  }
  componentWillReceiveProps(nextProps) {
    const { username } = nextProps.params;
    this.fetchUser(username);
  }
  fetchUser(username) {
    const { dispatch } = this.props;
    dispatch(fetchUser(username));
  }
  render() {...}
}

export default connect((state, ownProps) => {
  return {
    username: ownProps.params.username,
    isAuthenticated: state.auth.isAuthenticated
  };
})(Profile);

而 fetchUser 操作看起来像这样(redux-api-middleware):

function fetchUser(id) {
  let token = localStorage.getItem('jwt');
  return {
    [CALL_API]: {
      endpoint: `http://localhost:3000/api/users/${id}`,
      method: 'GET',
      headers: { 'x-access-token': token },
      types: [FETCH_USER_REQUEST, FETCH_USER_SUCCESS, FETCH_USER_FAILURE]
    }
  }
}

我添加 componentWillReceiveProps 函数的原因是在 URL 更改为另一个 :username 时做出反应并加载该用户的个人资料信息。乍一看,一切似乎都正常,但后来我注意到在调试时 componentWillReceiveProps 函数在无限循环中被调用,我不知道为什么。如果我删除 componentWillReceiveProps 则配置文件不会使用新用户名更新,但我没有循环问题。有什么想法吗?

【问题讨论】:

    标签: reactjs react-router redux react-redux react-router-redux


    【解决方案1】:

    您的componentWillReceiveProps 处于无限循环中,因为调用fetchUser 将调度一个更新道具的动作。

    添加一个比较,以在调度操作之前检查特定的道具是否发生变化。 编辑:

    React 16.3+ 中,componentWillReceiveProps 将慢慢弃用

    建议使用componentDidUpdate 代替componentWillReceiveProps

    componentDidUpdate(prevProps) {
      if (this.props.params.username !== prevProps.params.username) {
        dispatch(fetchUser(username));
      }
    }
    

    https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data-when-props-change

    【讨论】:

    • 我现在明白了。 FETCH_USER_SUCCESS 的 reducer 存储了我的 Profile 组件正在连接的一些用户数据(我在写问题时忘记将其添加到上面的代码中)。所以流程是 componentWillReceiveProps --> dispatcher --> reducer 更新 Profile 连接的数据 --> componentWillReceiveProps 再次被调用,一切重新开始。我想我需要将路由更改的代码移到其他地方以避免这个循环。谢谢!
    【解决方案2】:

    尝试添加条件来比较道具。如果您的组件需要它。

    componentWillRecieveProps(nextProps){
     if(nextProps.value !== this.props.value)
      dispatch(action()) //do dispatch here 
    }
    

    【讨论】:

      【解决方案3】:

      如果您使用一些路径参数(例如 profile/:username)来响应路由, 您可以简单地比较 props.location.pathname

      componentWillReceiveProps(nextProps){    
          if(nextProps.location.pathname !== this.props.location.pathname){
                dispatch()
              }
       }  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-02
        • 2019-02-09
        • 1970-01-01
        • 2020-02-26
        • 2020-08-20
        • 2015-08-02
        相关资源
        最近更新 更多