如何仅当一个对象在 useSelector 中发生更改时才导致重新渲染

How to cause a rerender only if one object changes in a useSelector

我有一个对象在我的状态下有多个值,但我只需要听一个来改变。

示例:

在第一次重新渲染时,我可能会看到类似这样的东西。

loading: {
  objectone: false,
  objecttwo: false, 
  objectthree: false, 
}

在第二次重新渲染时,我可能会看到状态更改为如下所示:}

    loading: {
      objectone: true,
      objecttwo: false, 
      objectthree: false, 
    }

然后状态进一步改变以将其他两个对象更新为 true。

    loading: {
      objectone: true,
      objecttwo: true, 
      objectthree: true, 
    }

每次加载状态中的对象之一发生变化时,都会导致在我的 useSelector 中重新呈现。

如果我只想要第一个对象中的信息 objectone。我怎么能在我的 useSelector 中写这个,以便它不会在其他两个对象更新时触发重新渲染?

我尝试过的事情:

之前

  const loadingStatus = useSelector(({ loading }) => loading);

之后
  const loadingStatus = useSelector(({ loading }) => {
    return loading.objectone ? true : false;
  });

这是一个例子,当 objectone 没有改变时,你的第二个选择器应该可以工作并且不会重新渲染:

const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;

const initialState = {
  loading: {
    objectone: false,
    objecttwo: false,
    objectthree: false,
  },
};
//action types
const CHANGE_LOADING = 'CHANGE_LOADING';
//action creators
const changeLoading = (whatLoading) => ({
  type: CHANGE_LOADING,
  payload: whatLoading,
});
const reducer = (state, { type, payload }) => {
  if (type === CHANGE_LOADING) {
    return {
      ...state,
      loading: {
        ...state.loading,
        [payload]: !state.loading[payload],
      },
    };
  }
  return state;
};
//selectors
const selectLoading = (state) => state.loading;
const createSelectWhatLoading = (what) =>
  createSelector(
    [selectLoading],
    (loading) => loading[what]
  );
//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 Loading = React.memo(function Loading() {
  console.log('rendeing loading');
  const dispatch = useDispatch();
  const selectObjectOne = React.useMemo(
    () => createSelectWhatLoading('objectone'),
    []
  );
  const objectone = useSelector(selectObjectOne);
  return (
    <div>
      <p>objectone is {String(objectone)}</p>
      <button
        onClick={() => dispatch(changeLoading('objectone'))}
      >
        Change objectone
      </button>
      <button
        onClick={() =>
          dispatch(changeLoading('objecttwo'))
        }
      >
        Change objecttwo
      </button>
    </div>
  );
});
const App = () => {
  return <Loading />;
};

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>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>