简体   繁体   English

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

[英]How to set useReducer initial state using API response?

I'm new to React and trying to build an app with a cart feature where users can add robots to the cart.我是 React 的新手,正在尝试构建一个具有购物车功能的应用程序,用户可以在其中将机器人添加到购物车中。 I'm using Context API to provide cart across the app and useReducer for states.我正在使用Context API为整个应用程序提供购物车,并为状态使用useReducer The robots are being fetched from a server and load just fine.机器人正在从服务器获取并加载得很好。 But I can't seem to find a way to set the initial state of the reducer using fetched products.但我似乎找不到使用获取的产品设置reducer的初始 state 的方法。 The state always returns an empty array for robots. state 始终为机器人返回一个空数组。 How to solve this?如何解决这个问题?

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 will not monitor changes to initialState , it will only consider its initial value. useReducer不会监控initialState的变化,它只会考虑它的初始值。 You can just dispatch an action to update the state once the data is fetched.获取数据后,您只需调度一个操作即可更新 state。

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;

If the nested components don't work well until the state is populated then you can conditionally render the provider:如果嵌套组件在填充 state 之前无法正常工作,那么您可以有条件地呈现提供程序:

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

Since the initial state value is fetched asynchronously you'll need to dispatch an action to set the state value.由于初始 state 值是异步获取的,因此您需要调度一个操作来设置state值。

Example:例子:

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

    case 'INITIALIZE_CART': 
      return action.payload;

    default:
      return state;
  }
};

CartProvider购物车提供者

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>
  );
};

It's common to also hold some state on the app initialization status.在应用程序初始化状态中还保留一些 state 是很常见的。 UI conditionally renders based on this state value. UI 基于此 state 值有条件地呈现。

Example:例子:

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;
  }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM