问题描述
我有几个使用相同的reducer的动作,而不是在每个动作中都进行dom操作,我想将其添加到共享的reducer中一次。我知道减速器是纯粹的(返回的数据仍然是纯正的),但这是某种反模式还是可以接受的策略?
case APPEND_POSTS:
!payload.length &&
document.getElementById('posts-cont').classList.add('no-more-posts'); // this
const total = state.posts.length + payload.length;
const limit = total > posts_to_keep_limit ? 50 : 0;
return {
...state,posts: [...state.posts.slice(limit),...payload],loading: false,};
```
解决方法
Redux Action
case APPEND_POSTS:
// you don't need to use below code.
// !payload.length && document.getElementById('posts-cont').classList.add('no-more-posts'); // this
const total = state.posts.length + payload.length;
const limit = total > posts_to_keep_limit ? 50 : 0;
return {
...state,posts: [...state.posts.slice(limit),...payload],nomore: true,loading: false,};
您的组件。
function YourComp(props){
const state = useSelector(...);
return ( <div id="posts-cont" className={state.nomore ? 'no-more-posts' : ''} > {...}</div>
}
,
我知道reducer是纯函数(返回的数据仍然是纯函数),但这是某种反模式还是可接受的策略?
返回的数据是纯数据,但是您已经以DOM突变的形式引入了副作用。因此,该减速器不是纯净的。
这确实是一种反模式,因为现在,渲染posts-cont
个项目的组件与该化简器之间存在不可见的耦合。它使您的代码库更难以阅读和调试。
jinongun的建议是好的:让组件的className使用选择器从商店的状态派生其值。一般问题的答案
我有几个使用相同的reducer的动作,而不是 在每个操作中都有一个dom操作,我只想添加它 一次进入我的共享reduce。
永远不要在化简器中进行DOM操作。 永远不要进行任何非纯计算的操作。
但是您可以创建一个总是会产生副作用的动作创建者(使用Redux-Thunk):
function appendPosts(payload) {
return dispatch => {
mySideEffect()
dispatch({
type: APPEND_POSTS,payload
})
}
}
function action1(params) {
return dispatch => {
dispatch({
type: ACTION1,payload: params
})
dispatch(appendPosts(params))
}
}
function action2(params) {
return dispatch => {
dispatch({
type: ACTION2,payload: params
})
dispatch(appendPosts(params))
}
}
// etc