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.