Home > OS >  Passing state through context in react gives error: TS2339: Property 'setImage' does not e
Passing state through context in react gives error: TS2339: Property 'setImage' does not e

Time:08-24

I am trying to figure out why my state and setState function are not recognized as part of my created context. I hope someone could explain to me what I am doing wrong!

This is my context file:

import React, {ReactNode, useEffect, useState} from 'react'

const PlantContext = React.createContext({});

interface Props {
    children?: ReactNode
}

const PlantContextProvider = ({children, ...props}: Props) => {

    const [image, setImage] = useState<string>('')

    useEffect(() => {

    }, [])

    return <PlantContext.Provider value={{
    image, setImage
    }}>
    {children}
    </PlantContext.Provider>
}

export {PlantContext, PlantContextProvider}

My components are wrapped in the PlantContextProvider element in App.tsx, and this is how I am trying to use the context in a child component:

import React, {useContext, useEffect, useState} from 'react';
import {PlantContext} from "../../../contexts/PlantContext";

function AddPlantBtn() {
    const plant = useContext(PlantContext)
    const input = document.getElementById('uploadImage') as HTMLInputElement;
    const file = input?.files![0]
    const [imageTaken, setImageTaken] = useState(false)
    useEffect(() => {
        plant.setImage(file) //THIS IS WHERE THE ERROR IS THROWN, SETIMAGE IS MARKED RED
    }, [imageTaken]);
    
    return (
        <>
            <label htmlFor='uploadImage'>
                <span className="btn btn-sm text-base-100 btn-primary m-2"><i className='material-symbols-rounded mr-2 text-base'>add_circle</i>Add plant</span>
                <input onChangeCapture={() => {setImageTaken(true)}} id='uploadImage' type="file" accept="image/*" capture="environment" hidden/>
            </label>
        </>
    );
}

export default AddPlantBtn;

CodePudding user response:

Provide a default* context value and type interface.

interface IPlantContext {
  image: string,
  setImage: React.Dispatch<React.SetStateAction<string>>,
}

const PlantContext = React.createContext<IPlantContext>({
  image: '',
  setImage: () => {},
});

This is basically only defining the shape of the Context value, the types are generally inferred, though you generally need to fully quantify the React state updater function. The PlantContextProvider component still holds and initializes the state and value its providing.

* Note: The defaultValue argument is only used when a component does not have a matching Provider above it in the tree.

  • Related