在 componentWillReceiveProps 中调度时的无限循环
Posted
技术标签:
【中文标题】在 componentWillReceiveProps 中调度时的无限循环【英文标题】:infinite loop when dispatching in 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 则配置文件不会使用新用户名更新,但我没有循环问题。有什么想法吗?
【问题讨论】:
【参考方案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()
【讨论】:
以上是关于在 componentWillReceiveProps 中调度时的无限循环的主要内容,如果未能解决你的问题,请参考以下文章
在 React 应用程序中在哪里转换数据 - 在 Express 中还是在前端使用 React?