我有一个连接到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);
};
提前谢谢!
答案 0 :(得分:1)
明确的答案是,鉴于您的实施,这是预期的行为。您将isFetching
状态映射到道具。以下是发生的事情:
状态树中isFetching
的初始值为false
,因此isFetching
prop值为false
,因此呈现为false
}。
您发送的操作会在状态树中将isFetching
更改为true
。此新状态将映射到新isFetching
道具值true
,这会导致重新渲染,其呈现为true
。
您(异步)调度另一个操作,将状态树中的isFetching
更改回false
。与(2)中的相同,这会导致重新呈现,isFetching
为false
。
如果您只想使用当前实现的true, false
*渲染,那么简单的解决方案就是在缩减器的初始状态中将isFetching
设置为true
。< / p>
这个实现在这个组件的设计级别上是否有意义是一个更广泛的问题,在这里没有足够的上下文回答: - )
完整性 *更新我应该说我不知道render()
函数是否会被调用两次,isFetching
被解析为true,false
或者在这种情况下使用true,true,false
三次。我怀疑react-redux可以优化组件的渲染,这样如果映射的isFetching
道具从true
- > true
改变,则不会重新渲染,但是不要我肯定知道这一点 - 如果你能告诉我你的日志记录输出会不会感激和感兴趣?
在任何情况下,由于标准的反应虚拟DOM差异优化,在DOM级别肯定只会发生两次渲染,所以实际上结果是相同的