0

我想了解 react-redux,但我完全不知道为什么组件没有更新。我认为没有任何更新,因为 react 没有考虑上下文变化的深度。但即使有这些想法我也不知道该怎么办请帮助我我累了

const MainContext = React.createContext(null);

const createStore = (reducer, initialState) => {
  let currentState = initialState;
  let listeners = [];

  const getState = () => currentState;
  const dispatch = (action) => {
    currentState = reducer(currentState, action);
    listeners.forEach((listener) => listener());
  };

  const subscribe = (listener) => listeners.push(listener);
  return { getState, dispatch, subscribe };
};

我认为错误在这里的某个地方

const useSelector = (selector) => {
  const ctx = React.useContext(MainContext);
  if (!ctx) {
    return 0;
  }
  return selector(ctx.store.getState());
};

const useDispatch = () => {
  const ctx = React.useContext(MainContext);
  if (!ctx) {
    return () => { };
  }
  return ctx.store.dispatch;
};

const Provider = ({ store, context, children }) => {

  const Context = context || MainContext;
  return <Context.Provider value={{ store }}>{children}</Context.Provider>

};

应用程序

const UPDATE_COUNTER = "UPDATE_COUNTER";
const CHANGE_STEP_SIZE = "CHANGE_STEP_SIZE";

const updateCounter = (value) => ({
  type: UPDATE_COUNTER,
  payload: value,
});
const changeStepSize = (value) => ({
  type: CHANGE_STEP_SIZE,
  payload: value,
});

const defaultState = {
  counter: 1,
  stepSize: 1,
};
const reducer = (state = defaultState, action) => {
  switch (action.type) {
    case UPDATE_COUNTER:
      return {
        ...state,
        counter: state.counter + action.payload,
      };
    case CHANGE_STEP_SIZE:
      return {
        ...state,
        stepSize: +action.payload,
      };
    default:
      return state;
  }
};

const Counter = () => {
  const counter = useSelector((state) => state.counter);
  const stepSize = useSelector((state) => state.stepSize);
  const dispatch = useDispatch();

  return (
    <div>
      <button onClick={() => dispatch(updateCounter(-stepSize))}>-</button>
      <span> {counter} </span>
      <button onClick={() => dispatch(updateCounter(stepSize))}>+</button>
    </div>
  );
};
const Step = () => {
  const stepSize = useSelector(
    (state) => state.stepSize,
    (current, prev) => current === prev
  );
  const dispatch = useDispatch();

  return (
    <div>
      <div>
        Значение счётчика должно увеличиваться или уменьшаться на заданную
        величину шага
      </div>
      <div>Текущая величина шага: {stepSize}</div>
      <input
        type="range"
        min="1"
        max="5"
        value={stepSize}
        onChange={({ target }) => dispatch(changeStepSize(target.value))}
      />
    </div>
  );
};

ReactDOM.render(
  <Provider store={createStore(reducer, defaultState)}>
    <Step />
    <Counter />
  </Provider>,
  document.getElementById("app")
);

4

1 回答 1

0

您的useSelector钩子实施错误,因为它从不订阅商店。因此,它不会在更新后再次检查状态 - 只有当组件碰巧由于其他原因重新渲染时。

有关 React-Redux 实际工作原理的详细信息,请参阅我的博文The History and Implementation of React-Redux和我的演讲ReactNext 2019: A Deep Dive into React-Redux

于 2020-09-04T21:16:37.797 回答