React 中的 Redux 调用多个调度函数

IT技术 reactjs redux react-redux
2021-05-16 09:59:48

我有一个调用动作的 index.js。一旦它调用一个动作,我想在该动作中触发多个调度动作。Index.js 调用 handLoadCustomers,它将调度 loadCustomers 函数,该函数调用 API 并调度另一个函数以将客户存储在状态中。

完成后,调用返回到 handleLoadCustomers,我想在第一次调用时使用客户,然后与将调用另一个函数/操作的那些客户分派 handleExtraCustomerLoads 的另一个操作。我如何在 React Redux 中做到这一点?

export function handleLoadCustomers() {
  return function (dispatch) {
    dispatch(loadCustomers())
      .then((customers) => {
        dispatch(handleExtraCustomerLoads(customers));
      })
      .catch((error) => {
        throw error;
      })
      .then((newCustomers) => {
        dispatch(handlePageLoadSuccess(newCustomers));
      });
  };



export function loadCustomers() {
  return function (dispatch) {
    return getCustomers()
      .then((customers) => {
        dispatch(loadCustomerSuccess(customers));
      })
      .catch((error) => {
        throw error;
      });
  };
}


在 loadCustomers 为空之后的客户,它根本不分派 handleExtraCustomerLoads 函数

1个回答

您不应使用操作的返回值,但您可以等待它完成并从状态中选择结果(我假设该操作会将您需要的数据写入商店)。

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

const initialState = {
  customers: [],
  extra: [],
};
//api
const getCustomers = () => Promise.resolve([1, 2, 3]);
//action types
const CUSTOMERS_SUCCESS = 'CUSTOMERS_SUCCESS';
const EXTRA = 'EXTRA';
//action creators
const loadCustomerSuccess = (customers) => ({
  type: CUSTOMERS_SUCCESS,
  payload: customers,
});
const handleExtraCustomerLoads = (extra) => ({
  type: EXTRA,
  payload: extra,
});
function handleLoadCustomers() {
  return function (dispatch, getState) {
    dispatch(loadCustomers()).then(() => {
      const customers = selectCustomers(getState());
      dispatch(handleExtraCustomerLoads(customers));
    });
  };
}
function loadCustomers() {
  return function (dispatch) {
    return getCustomers()
      .then((customers) => {
        //you need to return the value here
        return dispatch(loadCustomerSuccess(customers));
      })
      .catch((error) => {
        throw error;
      });
  };
}

const reducer = (state, { type, payload }) => {
  if (type === CUSTOMERS_SUCCESS) {
    return { ...state, customers: payload };
  }
  if (type === EXTRA) {
    return { ...state, extra: payload };
  }
  return state;
};
//selectors
const selectCustomers = (state) => state.customers;
const selectExtra = (state) => state.extra;
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware((store) => (next) => (action) =>
      //diy thunk
      typeof action === 'function'
        ? action(store.dispatch, store.getState)
        : next(action)
    )
  )
);
const App = () => {
  const dispatch = useDispatch();
  const customers = useSelector(selectCustomers);
  const extra = useSelector(selectExtra);
  return (
    <div>
      <button
        onClick={() => dispatch(handleLoadCustomers())}
      >
        load customers
      </button>
      <pre>
        {JSON.stringify({ customers, extra }, undefined, 2)}
      </pre>
    </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>
<div id="root"></div>