4

我有几个使用相同减速器的动作,而不是在每个动作中都有一个 dom 操作,我只想在我的共享减速器中添加一次。我知道减速器是纯粹的(返回的数据仍然是),但这是某种反模式还是可接受的策略?

 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,
      };
    ```
4

3 回答 3

4

还原动作

 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>

 
} 
于 2020-08-19T05:16:45.087 回答
3

我知道减速器是纯粹的(返回的数据仍然是),但这是某种反模式还是可接受的策略?

返回的数据是纯数据,但是您以 DOM 突变的形式引入了副作用。所以这个reducer不是纯的。

这确实是一种反模式,因为现在,渲染posts-cont项目的组件与这个 reducer 有一个不可见的耦合。它使您的代码库更难阅读和调试。

于 2020-08-19T05:18:55.343 回答
1

jinongun 的建议很好:让组件的 className 使用选择器从商店的状态中获取其值。至于一般问题

我有几个使用相同减速器的动作,而不是在每个动作中都有一个 dom 操作,我只想在我的共享减速器中添加一次。

永远不要在 reducer 中进行 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
于 2020-08-19T06:01:53.010 回答