使用Redux的异步操作
Async Action with Redux
我有一个连接到Redux商店的React组件。我正在componentWillMount
生命周期方法中获取资源(帖子)。
componentWillMount() {
this.props.fetchPosts();
}
组件将订阅Redux存储,并从存储中获取isFetching
和posts
。
const mapStateToProps = (state) => {
return {
posts: getAllPosts(state),
isFetching: getIsFetchingPosts(state),
}
}
我想在它仍在获取时显示一个微调器,所以在render
方法中我想这样做。
render() {
if (this.props.isFetching) {
return <Spinner />
}
return this.props.posts.map(post => <PostItem key={post.id}{...post}/>)
}
但如果我在render
方法中控制台.log isFetching
,它首先显示false
,然后显示true
,最后显示false
。
理想情况下,当该容器首次渲染时,isFetching
状态已设置为true
并显示微调器。我需要做什么改变才能实现这一点?
以下是动作创建者和减速器的代码
/*** Action Creator ***/
export const fetchPosts = () => (dispatch) => {
dispatch({
type: REQUEST_POSTS,
});
return axios({
method: 'get',
url: `${API_URL}/posts`,
})
.then(({data}) => {
dispatch({
type: RECEIVE_POSTS,
payload: data.posts,
})
})
.catch((response) => {
// some error handling.
});
}
/*** Reducers ***/
const initialState = {
isFetching: false,
allIds: [],
byId: {},
};
const isFetching = (state = initialState.isFetcthing, action) => {
switch (action.type) {
case REQUEST_POSTS:
return true;
case RECEIVE_POSTS:
return false;
default:
return state;
}
}
const allIds = (state = initialState.allIds, action) => {
switch (action.type) {
case RECEIVE_POSTS:
return action.payload.map(post => post.id);
default:
return state;
}
}
const byId = (state = initialState.byId, action) => {
switch (action.type) {
case RECEIVE_POSTS:
return action.payload.reduce((nextState, post) => {
nextState[post.id] = post;
return nextState;
}, {...state});
default:
return state;
}
}
const posts = combineReducers({
isFetching,
allIds,
byId,
});
export default posts;
/*** Selectors in 'posts.js' file ***/
export const getAllPosts = (state) => {
const { allId, byId } = state;
return allIds.map(id => byId[id]);
}
/*** rootReducer file ***/
import posts, * as fromPosts from './posts';
const rootReducer = combineReducers({
posts,
})
export default rootReducer;
export const getAllPosts = (state) => {
return fromPosts.getAllPosts(state.posts);
};
提前谢谢!
简单的答案是,考虑到您的实现,这是预期的行为。您正在将isFetching
状态映射到道具。发生了什么:
-
状态树中
isFetching
的初始值是false
,因此isFetching
的道具值是false
,因此它呈现为false
。 -
您调度一个将状态树中的
isFetching
更改为true
的操作。此新状态被映射到true
的新isFetching
道具值,这将导致重新渲染,并在其中渲染为true
。 -
您(异步)调度另一个操作,将状态树中的
isFetching
更改回false
。与(2)中相同,这会导致重新渲染,isFetching
为false
。
如果您只想在当前实现中渲染true, false
*,那么简单的解决方案是在reducer的初始状态中将isFetching
设置为true
。
这个实现在这个组件的设计级别上是否有意义是一个更广泛的问题,这里没有足够的上下文来回答:-)
*update为了完整起见,我应该说我不知道render()
函数会被调用两次,其中isFetching
被解析为true,false
,在这种情况下,true,true,false
会被调用三次。我怀疑react redux可能会优化组件的渲染,这样,如果映射的isFetching
道具从true
->true
更改,就不会发生重新渲染,但我不确定这一点-如果你能让我知道你的日志输出是什么,我将不胜感激并感兴趣?
在任何情况下,由于标准的react虚拟DOM困难优化,在DOM级别上肯定只会发生两次渲染,因此无论哪种方式,结果都是相同的
- 如何指示“;熟度;在异步操作中
- 无法在Redux中测试异步操作
- 当我在异步操作Redux上开始单元测试时,没有定义错误承诺
- Redux 中的异步操作
- Redux - 智能组件 - 在挂载组件之前如何处理异步操作
- 反应 Redux 异步操作在完成函数后调用下一个函数
- 在redux中使用thunk中间件比使用常规函数作为异步操作创建者有什么好处
- 我们如何模拟Redux异步操作的fetch
- 我们如何在Redux异步操作中模拟fetch
- Redux异步操作测试的目的是什么
- 将回调函数传递给redux异步操作是否被认为是好的做法?
- Redux基于登录的异步操作
- Redux异步操作处理
- 如何在redux-thunk中断言在异步操作内部调度的异步操作
- React Redux和Redux -observable在异步操作完成后使用路由器导航到另一个页面
- 如何使用React/Redux (este stack)进行异步操作
- 如何用redux从异步操作中捕获错误
- 如何在使用Redux进行异步操作调度后检索状态数据
- 使用Redux的异步操作
- 如何取消React/Redux中挂起的异步操作