我工作一段时间以来一直与 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的方式,他没有提及错误的原因。
编辑:添加了代码段,表明该方法确实有效,并且不会执行错误的读取。
答案 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}/>
)}
</>
);
}
}