【问题标题】:Running a React functional component with redux store.subscribe使用 redux store.subscribe 运行 React 功能组件
【发布时间】:2021-06-09 16:09:01
【问题描述】:

考虑下面的 react 代码(也包括 redux)

store = createStore(todoApp) ;
store.subscribe(App);

export default function App(){
  .....
}

这意味着对于我的 App 功能组件中发生的每个调度操作,App 必须呈现,因为 subscribe 执行封闭的 function 。然而,我观察到的是,虽然该函数执行 HTML 组件并没有得到更新,并且即使在多次调度操作之后,从第一次渲染仍然保持不变。谁能解释这种行为?

【问题讨论】:

  • 这不是你在 react 中使用 redux 的方式,你可以使用钩子 useSelectoruseDispath 或 HOC connect 两者都和 Provider 一起使用

标签: reactjs redux react-redux


【解决方案1】:

这不是您将 React 应用程序连接到 redux 存储的方式。这是一个使用 Provider 和 react-redux 钩子的示例应用程序:

//you would import these with
//  import {Provider} from 'react-redux'
const { Provider, useDispatch, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { createSelector } = Reselect;
const { memo, useMemo, useCallback } = React;

const initialState = {
  counters: [
    { id: 1, count: 1 },
    { id: 2, count: 1 },
    { id: 3, count: 1 },
  ],
};
//action types
const ADD = 'ADD';
//action creators
const add = (id) => ({
  type: ADD,
  payload: id,
});
const reducer = (state, { type, payload }) => {
  if (type === ADD) {
    return {
      ...state, //not needed in this case but usually is
      counters: state.counters.map(
        (counter) =>
          counter.id === payload
            ? { ...counter, count: counter.count + 1 }
            : counter //do not update this counter (not the right id)
      ),
    };
  }
  return state;
};
//selectors
const selectCounters = (state) => state.counters;
const createSelectCounterById = (counterId) =>
  createSelector(
    [selectCounters], //re use select counters
    (
      counters //got the counters, find the right counter
    ) => counters.find(({ id }) => id === counterId)
  );
//select sum of all counters
const selectSum = createSelector(
  [selectCounters], //re use select counters
  (counters) =>
    //reduce counters array to a number
    counters.reduce(
      (result, counter) => result + counter.count,
      0
    )
);
//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 Counter = memo(function Counter({ id, addAction }) {
  const selectCounter = useMemo(
    () => createSelectCounterById(id),
    [id]
  );
  const counter = useSelector(selectCounter);
  return (
    <li>
      {counter.count}
      <button onClick={() => addAction(id)}>+</button>
    </li>
  );
});
const Total = memo(function Total() {
  const sum = useSelector(selectSum);
  return <h3>{sum}</h3>;
});
const App = () => {
  const counters = useSelector(selectCounters);
  const dispatch = useDispatch();
  const addAction = useCallback(
    (id) => dispatch(add(id)),
    //dispatch is not really a dependency but
    //  linter doesn't know that and adding
    //  it doesn't change behavior
    [dispatch]
  );
  return (
    <div>
      <Total />
      <ul>
        {counters.map(({ id }) => (
          //id property here is not html id element property
          <Counter key={id} id={id} addAction={addAction} />
        ))}
      </ul>
    </div>
  );
};

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

【讨论】:

  • 感谢您的回复。但是为什么有问题的代码不起作用?因为对于每次调度,商店都被订阅并且封闭的(APP函数)函数应该重新执行
  • @ShaikWasef 再说一遍:That is not how you connect your React application to the redux store. 你的组件 App 将由 Redux 调用,而不是由 React 调用,因此不会呈现任何内容,因为 App 函数没有什么特别之处,它只会在 React 调用时向 DOM 渲染一些东西。
猜你喜欢
  • 2020-11-19
  • 2020-08-07
  • 2023-04-10
  • 1970-01-01
  • 2020-09-18
  • 2019-08-06
  • 2017-10-14
  • 2017-02-14
  • 2020-04-08
相关资源
最近更新 更多