Issue
Hi :) I'm running into an issue when trying to set up context with createContext. I need/want to access state and dispatch in my child components.
I'd also like to know: is the way I'm trying to pass down state and dispatch the right way? Or is there another (better) way to do this?
The error I get: No value exists in scope for the shorthand property 'state'. Either declare one or provide an initializer.
Here's (part of) my App.tsx:
interface IState {
hasStarted: boolean;
chosenAmount: string;
chosenCategory: string;
chosenDifficulty: string;
}
const initialState: IState = {
hasStarted: false,
chosenAmount: "",
chosenCategory: "",
chosenDifficulty: "",
};
// ...
interface IStateContext {
state: IState
dispatch: React.Dispatch<Action>
}
export const StateContext = createContext<IStateContext>({state, dispatch}); // error here
export const App: React.FC = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<StateContext.Provider value={{state, dispatch}}>
{state.hasStarted ? <QuestionsPage /> : <StartPage dispatch={dispatch} />}
</StateContext.Provider>
);
};
Solution
{ a } is shorthand for: { a: a }
If a exists, then this works fine:
const a = 123
const obj = { a }
But if it does not then you get this error:
const obj = { a }
// No value exists in scope for the shorthand property 'a'.
// Either declare one or provide an initializer.(18004)
Which means that this line:
export const StateContext = createContext<IStateContext>({state, dispatch});
calls the createContext function with an argument that is an object with two values named state and dispatch.
The problem is that when this function called those values don't exist yet. That's what this error means:
No value exists in scope for the shorthand property 'state'.
Create an object via { state } expects there to be a value named state that will be the value of the state property of the object.
To fix it you need to provide the createContext() with a proper default object. That means it must fully confirm to the IStateContext type.
Something like:
const initialState: IState = {
hasStarted: false,
chosenAmount: "",
chosenCategory: "",
chosenDifficulty: "",
};
export const StateContext = createContext<IStateContext>({
state: initialState,
dispatch: (action: Action) => undefined
);
I, personally, prefer this little hook that will throw an error if a context is used without a provider as a parent. This means you don't need to define a default value at all, and for large and complex contexts, that is really nice.
Answered By - Alex Wayne
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.