如何使用 API 响应设置 useReducer 初始状态?

How to set useReducer initial state using API response?

我是 React 的新手,正在尝试构建一个具有购物车功能的应用程序,用户可以在其中将机器人添加到购物车。我正在使用 Context API 在整个应用程序中提供购物车,并在各州使用 useReducer。正在从服务器获取机器人并加载得很好。但我似乎无法找到一种方法来使用获取的产品设置 reducer 的初始状态。状态总是 returns 机器人的空数组。如何解决?

const CartProvider = ({ children }) => {
    const [robots, setRobots] = useState([]);

    useEffect(() => {
        fetch('http://localhost:8000/api/robots')
            .then(res => res.json())
            .then(data => setRobots(data?.data))
    }, [])

    const initialState = {
        robots: [...robots],
        cart: []
    }
    const [state, dispatch] = useReducer(cartReducer, initialState);

    return (
        <CartContext.Provider value={{ state, dispatch }}>
            {children}
        </CartContext.Provider>
    );
}
export default CartProvider;
const [state, dispatch] = useReducer(cartReducer, initialState);

useReducer不会监听initialState的变化,只会考虑它的初始值。获取数据后,您可以调度一个操作来更新状态。

const initialState = {
    robots: [],
    cart: []
}

const CartProvider = ({ children }) => {
    const [state, dispatch] = useReducer(cartReducer, initialState);

    useEffect(() => {
        fetch('http://localhost:8000/api/robots')
            .then(res => res.json())
            .then(data => {
                // dispatch action to update the reducer state 
            })
    }, [])
    

    return (
        <CartContext.Provider value={{ state, dispatch }}>
            {children}
        </CartContext.Provider>
    );
}
export default CartProvider;

如果嵌套组件在填充状态之前无法正常工作,那么您可以有条件地呈现提供程序:

  return (
    <>
      {state.robots.length && (
        <CartContext.Provider value={{ state, dispatch }}>
          {children}
        </CartContext.Provider>
      )}
    </>
  );

由于初始状态值是异步获取的,因此您需要分派一个操作来设置 state 值。

示例:

const cartReducer = (state, action) => {
  switch(action.type) {
    ... other reducer cases ...

    case 'INITIALIZE_CART': 
      return action.payload;

    default:
      return state;
  }
};

购物车提供商

const initialState = {
  robots: [],
  cart: []
};

const CartProvider = ({ children }) => {
  const [robots, setRobots] = useState([]);

  const [state, dispatch] = useReducer(cartReducer, initialState);

  useEffect(() => {
    fetch('http://localhost:8000/api/robots')
      .then(res => res.json())
      .then(data => {
        dispatch({
          type: 'INITIALIZE_CART',
          payload: {
            ...initialState,
            robots: data?.data,
          }
        });
      });
  }, []);

  return (
    <CartContext.Provider value={{ state, dispatch }}>
      {children}
    </CartContext.Provider>
  );
};

在应用程序初始化状态上也保存一些状态是很常见的。 UI 根据此状态值有条件地呈现。

示例:

const initialState = {
  initialized: false,
  robots: [],
  cart: []
};

...

const cartReducer = (state, action) => {
  switch(action.type) {
    ... other reducer cases ...

    case 'INITIALIZE_CART': 
      return {
        ...action.payload,
        initialized: true,
      };

    default:
      return state;
  }
};