#reactjs #typescript #react-context
Вопрос:
Сегодня утром я работал над торговым сайтом, используя API React Typescript и контекст, и хочу использовать редукторы React для управления состоянием моей корзины покупок с помощью пользовательских типов, которые я создал для типа продукта, включая массив товаров и некоторые функции … Проблема в том, что я не знаю, как передавать параметры с помощью действия в функции CartReducer, и хотел бы знать, как бы вы это сделали
Мой картотекст
import * as React from 'react';
import { useQuery } from "react-query";
type ICartContext = [IProductItem[] | undefined, React.Dispatch<React.SetStateAction<IProductItem[] | undefined>>];
export const CartContext = React.createContext<ICartContext>([[], () => null]);
type Action = "Add" | "Update" | "Remove"
const CartReducer = (state: IProductItem[], action: Action) => {
return state
}
const CartProvider: React.FC<{}> = ({children}: { children?: React.ReactNode }) => {
const [cart, setCart] = React.useReducer(CartReducer, [], undefined)
return (
<CartContext.Provider value={[cart, setCart]}>
{children}
</CartContext.Provider>
);
};
export default CartProvider;
Мои Типы
interface IProductItem{
id: number
title: string
description: string
category: string
image: string
price: number
quantity: number
}
type ProductType = {
items: IProductItem[];
saveItem: (item: IProductItem) => void
updateItem: (id: number) => void
removeItem: (id: number) => void
};
Ответ №1:
Используйте дискриминируемый союз в качестве типа вашего действия:
// each specific action includes a `type` property
interface AddAction {
type: "Add";
addedProduct: IProductItem;
}
interface UpdateAction {
type: "Update";
updatedProduct: IProductItem;
}
interface RemoveAction {
type: "Remove";
removedProduct: IProductItem;
}
// Action is a union of all the possible actions
type Action = AddAction | UpdateAction | RemoveAction;
const CartReducer = (state: IProductItem[], action: Action) => {
// Since `type` is the only property all actions have in common,
// it's the only property that can be accessed until narrowing
// it with a condition or a switch statement
switch (action.type) {
case "Add":
// can access action.addedProduct here
return state;
case "Update":
// can access action.updatedProduct here
return state;
case "Remove":
// can access action.removedProduct here
return state;
}
};
// elsewhere:
dispatch({ type: "Add", addedProduct: product })
Комментарии:
1. Привет @Стивен Дженнингс, спасибо за ваш ответ, я сделал то, что вы мне сказали, но когда я пытаюсь экспортировать
setState
значения поставщика, я получаю следующую ошибку… как я могу это исправить :Type 'Dispatch<Action>' is not assignable to type 'Dispatch<SetStateAction<IProductItem[] | undefined>>'. Type 'SetStateAction<IProductItem[] | undefined>' is not assignable to type 'Action'. Type 'undefined' is not assignable to type 'Action'.ts(2322)
2. Я думаю , что это исходит из типа
ICartContext
, его, вероятно, нужно обновить, чтобы принятьDispatch<Action>
вместоDispatch<SetStateAction<IProductItem[] | undefined>>
3. Да, я исправил это вчера, теперь все работает хорошо, спасибо за вашу помощь.. Ценю это