在响应生命周期中等待Redux重击

时间:2018-12-13 04:43:09

标签: javascript reactjs async-await react-redux redux-thunk

我工作一段时间以来一直与 React&Redux 合作 同事看到了我编写的一些代码并对此进行了评论。

SomeComponent.js

class SomeComponent extends Component {

  async componentDidMount() {
    await this.props.fetchPosts();  

    if (this.props.posts.length < 1)
      return navigateTo( /* someOtherPlace */);
  }

  render() {
    return (
        <>
          {this.props.posts.map(
            (postData, i) => <Post key={i} {...postData}/>
          )}
        </>
    );
  }
}

const mapStateToProps = ({ posts }) => ({
  posts: posts.list,
  isFetching: posts.isFetching
});

export default connect(mapStateToProps, { fetchPosts })(SomeComponent);

actions / posts.js

export const fetchPosts = () => async dispatch => {
  dispatch(requestPosts());
  let posts;
  try {
    posts = (await api.get('/posts')).data
  } catch (e) {
    posts = e;
  }
  dispatch(receivePosts(posts));
}

他基本上说我不应该等待fetchPosts()的动作,相反,我应该调用它,让它更新道具,重新渲染并在componentDidUpdate中执行条件导航,当他说了,这对我来说完全有意义。

但是现在我一直在问自己,我做的事真的是那么糟糕,潜在的越野车还是仅仅是增加了更多复杂性的不好的做法。

除了不是React的方式,他没有提及错误的原因。

编辑:添加了代码段,表明该方法确实有效,并且不会执行错误的读取。

Edit Await in componentDidMount

1 个答案:

答案 0 :(得分:0)

所以您的情况有小问题

async componentDidMount() {
    await this.props.fetchPosts();  

    if (this.props.posts.length < 1)
      return navigateTo( /* someOtherPlace */);
}

这里await将等到fetchPosts完成,只要它返回一个承诺。现在,fetchPosts将调度一个动作,该动作只会导致更新道具并触发另一个渲染器以更新组件中的帖子。因此,即使您等待fetchPosts完成posts也不会在同一渲染周期中更新,因此使用this.props.posts.length不会返回与Redux存储中最新帖子更新相对应的结果。结果是您不必要地等待fetchPosts完成并执行检查,这将导致错误的结果

更好的方法是像

class SomeComponent extends Component {

  componentDidMount() {
    this.props.fetchPosts();  
  }

  componentDidUpdate(prevProps) {
     if(this.props.posts !== prevProps.posts && this.props.posts.length < 1) {
          return navigateTo( /* someOtherPlace */);
     }
  }

  render() {
    return (
        <>
          {this.props.posts.map(
            (postData, i) => <Post key={i} {...postData}/>
          )}
        </>
    );
  }
}