简体   繁体   中英

Errors while creating a Single Context Provider in React TypeScript

I am trying to create a context for Cart by following this: https://github.com/AlexSegen/react-shopping-cart/blob/master/src/contexts/CartContext.js for a React TypeScript project.

I am confused of what does this Context take in as parameters. I am getting errors a multiple places. This is what I have written so far:

import React, { createContext, useReducer } from 'react';
import { CartReducer, sumItems } from './CartReducer';

export const CartContext = createContext({}); <-- 1) Ambiguity Here

type Props = { children: React.ReactElement }

const storage = localStorage.getItem('cart') ? JSON.parse(localStorage.getItem('cart')) : []; <-- Error1 here
const initialState = { cartItems: storage, ...sumItems(storage), checkout: false };

const CartContextProvider = ({children} : Props) => {
     const [state, dispatch] = useReducer(CartReducer, initialState)
     const increase = payload => {    <-- Error2 Here and for all Payloads below
          dispatch({ type: 'INCREASE', payload })
     }
     const decrease = payload => {
          dispatch({ type: 'DECREASE', payload })
     }
     const addProduct = payload => {
          dispatch({ type: 'ADD_ITEM', payload })
     }
     const removeProduct = payload => {
          dispatch({ type: 'REMOVE_ITEM', payload })
     }
     const clearCart = () => {
          dispatch({ type: 'CLEAR' })
     }
     const handleCheckout = () => {
          console.log('CHECKOUT', state);
          dispatch({ type: 'CHECKOUT' })
     }
     const contextValues = {
          removeProduct,
          addProduct,
          increase,
          decrease,
          clearCart,
          handleCheckout,
          ...state
     }
     return (
          <CartContext.Provider value={contextValues} >
               { children}
          </CartContext.Provider>
     );
}
export default CartContextProvider;  

These are the errors I am facing:

// Ambiguity Here:
I am not sure if I can pass an empty JSON object, it might be working for now, but Ideally in Typescript we must pass a parameter type. And I am wondering what Parameter(Interface) this context could take.

// Error1:
var localStorage: Storage
Argument of type 'string | null' is not assignable to parameter of type 'string'. Type 'null' is not assignable to type 'string'.ts(2345)

// Error2:
(parameter) payload: any
Parameter 'payload' implicitly has an 'any' type.ts(7006)

In order to fix this, I have tried following approaches:

// Fix for Error1:
const storage = localStorage.getItem('cart') ? JSON.parse(localStorage.getItem('cart') || '{}') : [];

// Fix for Error2:
type PropsforPayload = { payload: React.ReactElement }
const increase = (payload: PropsforPayload) => { //Similar for all the occurences.

My question here is: Are my two approaches valid? Will they be consistent through out and how do I correctly use the Context for types(interface)

1 - React.createContext argument is default value. It's used only when you get context value without provider. If there is no reasonable defaults, you might want to throw error in this case. I use null as default value and custom wrapper arround React.useContext which throws an error if this would happen. https://reactjs.org/docs/context.html#reactcreatecontext

2 - Typescript doesn't know that localStorage.getItem('cart') always returns the same value in this case, so when it's called the second time, typescript still thinks it might be null. So you should save it to a variable first:

const cartString = localStorage.getItem('cart');
const storage = cartString  ? JSON.parse(cartString) : [];

or

const storage = JSON.parse(localStorage.getItem('cart') ?? "[]");

3 - Typescript have no idea what is payload, so you should specify it manually. Alternatively you can try to use some typescript friendly library to do it ie https://github.com/piotrwitek/typesafe-actions#action-helpers

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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