我有一个连接到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}/>)
}
但是,如果我在
isFetching
方法中使用console.log render
,则首先显示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
的操作。此新状态映射到新的isFetching
属性值true
,这会导致重新渲染,并以true
的形式呈现。
您(异步)调度另一个动作,该动作将状态树中的isFetching
更改回false
。与(2)中相同,这会导致重新渲染,其中isFetching
为false
。
如果您只想使用当前实现对true, false
*进行渲染,那么简单的解决方案是在化简器的初始状态下将isFetching
设置为true
。
在组件的设计级别上,此实现是否有意义是一个更广泛的问题,即这里没有足够的上下文来回答:-)
*为了完整性的更新我应该说我不知道render()
函数是否会被调用两次,在这种情况下,将isFetching
解析为true,false
或使用true,true,false
调用三次。我怀疑react-redux可能会优化组件的渲染,以便如果映射的isFetching
道具从true
-> true
更改,则不会发生任何重新渲染,但不能确定这一点-将不胜感激是否有兴趣让我知道您的日志输出是什么?
无论如何,由于标准对虚拟DOM差异进行优化,在DOM级别上肯定只会发生两个渲染,因此实际上两种方法的结果都是相同的
关于javascript - 使用Redux的异步操作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38640125/