Reactjs 更新Redux状态后如何触发动作创建者
我正在构建一个React组件,其中列出了用户当天发布的所有帖子。我有两个动作创造者和还原者:Reactjs 更新Redux状态后如何触发动作创建者,reactjs,redux,redux-thunk,Reactjs,Redux,Redux Thunk,我正在构建一个React组件,其中列出了用户当天发布的所有帖子。我有两个动作创造者和还原者: fetchUserList()是一个操作创建者,它获取所有用户的列表,并被还原程序状态this.props.userList fetchPosts(userId)是一个动作创建者,它接受userId作为参数,并获取今天发布的帖子。这被reducer stateThis.props.postsList 组件的外观如下所示: class PostList extends Component { comp
fetchUserList()
是一个操作创建者,它获取所有用户的列表,并被还原程序状态this.props.userList
fetchPosts(userId)
是一个动作创建者,它接受userId
作为参数,并获取今天发布的帖子。这被reducer stateThis.props.postsList
class PostList extends Component {
componentDidMount() {
this.props.fetchUserList();
}
renderPosts = () => {
this.props.userList.forEach(user => {
this.props.fetchUsers(user._id);
});
this.setState({
renderedPosts: true
});
};
render() {
return (
<div>
{this.props.userList.length > 0 && !this.state.renderedPosts ? this.renderPosts() : ""}
</div>
);
}
类PostList扩展组件{
componentDidMount(){
this.props.fetchUserList();
}
renderPosts=()=>{
this.props.userList.forEach(用户=>{
this.props.fetchUsers(user.\u id);
});
这是我的国家({
RenderPosts:true
});
};
render(){
返回(
{this.props.userList.length>0&&!this.state.renderPosts?this.renderPosts():“”
);
}
当React尝试渲染此组件时,它会抱怨:
警告:在现有状态转换期间(例如在render
或其他组件的构造函数中)无法更新。渲染方法应该是道具和状态的纯函数;构造函数的副作用是反模式,但可以移动到componentWillMount
我尝试使用其他React生命周期方法,例如ComponentWillUpdate()
,并从那里调用操作,而不是render()
方法,但没有成功
处理这种模式的最佳方法是什么?首先,让我们试着理解为什么
React
会抱怨。您的代码试图做的是在组件渲染时更新状态。但是更新状态会导致重新渲染。因此,您可能会陷入无休止的循环:
渲染->更新状态->渲染->更新状态->…
出于这个原因,在渲染期间不应调用setState
。让我们试着看看如何实现这一点。我们希望首先获取用户,然后为每个用户获取该用户今天发布的帖子。由于您使用async
操作和redux thunk
,理论上可以将这些电话就像任何承诺一样。你可以在文档中找到几个例子。让我们来享受一些乐趣:
// In your action creators
function fetchUserList() {
return function(dispatch) {
return fetch('http://my-api/user-list').then(
userList => {
dispatch({
type: 'FETCH_USER_LIST',
userList: userList,
});
return Promise.resolve(userList);
}
);
};
}
function fetchPosts(userId) {
return function(dispatch) {
return fetch(`http://my-api/users/${userId}/posts`).then(
posts => {
dispatch({
type: 'FETCH_USER_POSTS',
userId: userId,
posts: posts,
});
return Promise.resolve(posts);
}
);
};
}
// Now in your component
class PostList extends Component {
componentDidMount() {
const { fetchUserList, fetchPosts } = this.props;
fetchUserList()
.then(users => {
const postsRequests = users.map(user => fetchPosts(user.id));
return Promise.all(postsRequests);
})
.then(() => this.setState({ renderedPosts: true }));
}
renderPost(post) {
// You can add more complete render logic here
return <p>{post}</p>;
}
render() {
const { postsList, userList } = this.props;
const { renderedPosts } = this.state;
return (
<div>
{userList.length > 0 && !renderedPosts
? postsList.map(post => renderPost(post))
: ""
}
</div>
);
}
//在动作创建者中
函数fetchUserList(){
返回功能(调度){
返回获取('http://my-api/user-list)。然后呢(
用户列表=>{
派遣({
键入:“获取用户列表”,
userList:userList,
});
返回Promise.resolve(用户列表);
}
);
};
}
函数fetchPosts(userId){
返回功能(调度){
回传(`http://my-api/users/${userId}/posts`)。然后(
职位=>{
派遣({
键入:“获取用户帖子”,
userId:userId,
职位:职位,
});
返回承诺。解决(帖子);
}
);
};
}
//现在在您的组件中
类PostList扩展组件{
componentDidMount(){
const{fetchUserList,fetchPosts}=this.props;
fetchUserList()
。然后(用户=>{
const postsRequests=users.map(user=>fetchPosts(user.id));
返回承诺。全部(后请求);
})
.then(()=>this.setState({rendereposts:true}));
}
renderPost(邮政){
//您可以在此处添加更完整的渲染逻辑
返回{post};
}
render(){
const{postsList,userList}=this.props;
const{renderedPosts}=this.state;
返回(
{userList.length>0&&!renderPosts
?postsList.map(post=>renderPost(post))
: ""
}
);
}
有几种方法可以实现这一点,查看文档应该很有启发性!它展示了几种组合和组合较小功能以构建您自己的流程的方法。与其从组件didmount
中链接这一点,我们可以有一个专门的action creator来为我们实现这一点。我希望这能给您带来更好的体验了解这些库和中间件的强大功能。我的代码片段只是一个简单的示例,它对您的代码/操作进行了一些假设,并跳过了所有“挂起”和“错误”状态
我建议不要使用
componentWillMount
,因为有充分的理由(请参阅和)。this.props.fetchUserList.forEach
这是否有效?不应该是this.props.userList.forEach
?您是否尝试移动到componentWillMount()
?@Prajwal抱歉,在复制粘贴代码时出错。为什么不摆脱renderedPost状态,只使用纯组件渲染帖子?这样,只有在更改后才会重新渲染。还可以尝试fetchTodaysPostForUsers(用户ID\u列表)操作,因此只有在所有结果都可用时,状态才会更新。我假设这里的获取是异步的。感谢这个答案,我需要花费一些时间来进一步研究它。我目前正在使用async/await语法-我假设我仍然可以使用它来连接调用,如您的示例中所示。确保没有问题,花费一些时间是值得的由于您将大量使用这些模式,因此需要花时间完全掌握它们。将其转换为async/await语法应该非常容易。让我知道这是怎么回事;)我正在努力用async/await语法复制它-您有一些代码可以与我共享吗?