【问题标题】:useSelector updating even if value hasn't changed即使值没有改变,useSelector 也会更新
【发布时间】:2021-01-27 14:11:27
【问题描述】:

我有一个组件订阅了商店的一部分并在之后触发了一个效果

const Component = (name) => {

  const query = useSelector((state) => getQuerySelector(state, name), shallowEqual);

  
  useEffect(() => {
    doStuff();
  }, [query]);

}

选择器看起来像

const getQuerySelector = (state, name) => state.innerReducer[name].query;

即使当reducer 使用与{value: true} 相同的值更新query(这是计算其他值的结果)时,选择器似乎每次都会更新。这是我的减速器的一部分:

case 'ACTION_X': 
  const query = {aProp: aValue, someOtherProp: someValue}
   
  return {
    ...otherData,
    query
  }

我也尝试使用createSelectormemoize 选择器,但没有成功。

【问题讨论】:

  • 您要更新的值(aValue、someValue)是数字或字符串等原始值还是对象?
  • 原始值

标签: reactjs redux react-redux


【解决方案1】:

我无法使用您提供的所有代码重现您描述的行为。也许您可以使用我的代码 sn-p 来重现您描述的行为:

const {
  Provider,
  useDispatch,
  useSelector,
  shallowEqual,
} = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const name = 'name';
const initialState = {
  innerReducer: {
    name: {
      query: { aProp: 8, someOtherProp: 8 },
    },
  },
};
//action types
const ACTION_X = 'ACTION_X';
//action creators
const actionX = () => ({
  type: ACTION_X,
});
const reducer = (state, { type }) => {
  console.log('reducing action:', type);
  if (type === ACTION_X) {
    const query = { aProp: 8, someOtherProp: 8 };
    return {
      ...state,
      innerReducer: {
        ...state.innerReducer,
        [name]: {
          ...state.innerReducer[name],
          query,
        },
      },
    };
  }

  return state;
};
//selectors
const getQuerySelector = (state, name) =>
  state.innerReducer[name].query;
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(() => (next) => (action) =>
      next(action)
    )
  )
);
const App = () => {
  const query = useSelector(
    (state) => getQuerySelector(state, name),
    //this shallowEqual will make sure that
    //{ aProp: 8, someOtherProp: 8 } quals { aProp: 8, someOtherProp: 8 }
    shallowEqual
  );
  const dispatch = useDispatch();
  console.log('rendering app');
  React.useEffect(
    () => console.log('Query in effect:', query),
    [query]
  );
  return (
    <div>
      <button onClick={() => dispatch(actionX())}>
        dispatch action x
      </button>
      <pre>{JSON.stringify(query, undefined, 2)}</pre>
    </div>
  );
};
console.log(
  'using shallowEqual:',
  shallowEqual(
    { aProp: 8, someOtherProp: 8 },
    { aProp: 8, someOtherProp: 8 }
  )
);
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>

也许你可以看看 redux devtools 并确保查询状态没有改变。可能组件重新渲染是因为父组件被重新渲染而你的组件不是纯组件,也可能组件被重新渲染是因为父组件传入了不同的 props。组件重新呈现但您的问题中的代码没有显示的原因可能有很多。

【讨论】:

    猜你喜欢
    • 2020-09-24
    • 2013-02-12
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 2013-08-30
    • 1970-01-01
    相关资源
    最近更新 更多