【问题标题】:Bad idea to put a dom operation inside a redux reducer?将 dom 操作放在 redux reducer 中是个坏主意?
【发布时间】:2020-08-19 05:09:41
【问题描述】:

我有几个使用相同reducer 的动作,而不是在每个动作中都有一个dom 操作,我只想在我的共享reducer 中添加一次。我知道 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,
      };
    ```

【问题讨论】:

  • 看起来很糟糕......你应该用 state 改变类
  • DOM 操作(98% 的情况)即使在组件中也应该避免,更不用说在 reducer 中了。如果某些效果必须与动作一起运行,请将它们放在动作创建器中或作为中间件。

标签: javascript reactjs redux anti-patterns redux-reducers


【解决方案1】:

Redux 操作

 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>

 
} 

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      我有几个使用相同减速器的动作,而不是 在每个动作中都有一个 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
      

      【讨论】:

        猜你喜欢
        • 2015-09-11
        • 2016-02-19
        • 1970-01-01
        • 2016-12-15
        • 2019-09-03
        • 2018-08-12
        • 2023-03-03
        • 2016-05-30
        • 2017-11-28
        相关资源
        最近更新 更多