0

I want to create a React Context and pass state and setState properties useState Hook down to a Consumer.

I have a Step and a Context types:

type Step = {
  step: string;
};

type Context = {
  step: Step;
  setStep: Dispatch<SetStateAction<Step>>;
};

I create a context:

export const StepContext = createContext<Context | undefined>(undefined);

I create a StepProvider and a hook:

const StepProvider = ({ children }: { children: ReactNode }) => {
  const [step, setStep] = useState<Step>({ step: 'one' });
  return <StepContext.Provider value={{ step, setStep }}>{children}</StepContext.Provider>;
};

I create a StepConsumer:

const StepConsumer = () => {
  const { step, setStep } = useContext(StepContext);
  return <div>{...}</div>;
};

But in:

const { step } = useContext(StepContext)

step and setStep return the following error TS2339: Property 'step' does not exist on type 'Context | undefined'

enter image description here

Am I not passing the types the right way?

Thanks

SixtyEight
  • 2,220
  • 3
  • 14
  • 25
  • The context type is determined by the initial value. To exclude `undefined`, you can encapsulate your context in a custom hook, as explained in [this answer](https://stackoverflow.com/a/60713501/5669456). – ford04 Mar 30 '20 at 19:05
  • Does this answer your question? [How to initialise the set function of useState for TypeScript in a createContext?](https://stackoverflow.com/questions/60712598/how-to-initialise-the-set-function-of-usestate-for-typescript-in-a-createcontext) – ford04 Mar 30 '20 at 19:06

1 Answers1

1

You're syntax is correct but usage of the context is not thorough enough to ensure the value is not undefined when deconstructing.

The error itself is checked by the strictNullChecks compiler option, your code will work in it's current state if strictNullChecks: false is set in your tsconfig.

However, to keep that option enabled you'll need to make sure the context value is not undefined before deconstructing or using the StepContext values, Typescript won't let you access it without checking first.

If you change the deconstruction to a simple assignment and then check the context is not undefined the error will go away.

const stepContext = React.useContext(StepContext);

if (typeof stepContext !== "undefined") {
  stepContext.setStep("foo")
}

// simplified
if (stepContext) {
  stepContext.setStep("foo")
}

// simplified further
stepContext?.setStep("foo");

Additionally, with strictNullChecks: false you're also able to define the context type without the undefined type value.

export const StepContext = createContext<Context>(undefined);
8eecf0d2
  • 1,569
  • 1
  • 13
  • 23