上下文提供者类型并在其他组件上获取值
Context Provider Type and get the value on other components
我正在使用 useContext 和 useReducer 来管理应用程序状态。
以下是片段:
//ReducerProvider.tsx
type ContextProviderType = {
state: StateInterface,
dispatch: React.Dispatch<ActionInterface>
}
type CreateContextType = ContextProviderType | string; // i am passing to the createContext either the ContextProviderType or a string (the string is just to initialize without errors since useReducer is not declared yet)
export const ReducerContext = React.createContext<CreateContextType>('');
interface ProviderProps {
children: ReactNode
}
export const ReducerProvider: React.FC<ProviderProps> = ({children}): JSX.Element => {
const [state, dispatch] = useReducer(reducer, initialState);
return <>
<ReducerContext.Provider value={{state, dispatch}}>
{children}
</ReducerContext.Provider>
</>
}
//App.tsx
const App: React.FC = (): JSX.Element => {
return <>
<ReducerProvider>
//components here so they can take the value of the provider component
</ReducerProvider>
</>;
}
只有当我尝试获取状态和分派值时才会出现错误,如下所示:
//Component.tsx
export const Component: React.FC = (): JSX.Element => {
const { state, dispatch } = useContext(ReducerContext)
//ERROR: Property 'state' does not exist on type 'CreateContextType'
//ERROR: Property 'dispatch' does not exist on type 'CreateContextType'
return (
<div className="box">
//...
</div>
)
}
但我不理解这个错误,因为我声明 CreateContextType 可以是字符串或 ContextProviderType,它是一个接收状态和调度参数的对象。
But I'm not understanding this error since I declared that CreateContextType can be either a string or a ContextProviderType,
这正是您收到错误的原因:您说它可能是一个字符串。如果它是一个字符串,那么它不会有 state
和 dispatch
属性。由于它可能没有这些属性,TypeScript 不会让您访问它们,除非您编写代码以确保它们首先存在。
检查字符串可能如下所示:
let state;
let dispatch;
const value = useContext(ReducerContext);
if (typeof value === 'string') {
throw new Error('Uh oh, i got a string');
} else {
({ state, dispatch }) = value;
}
这显然很麻烦,因此您可以将此检查提取到自定义挂钩中:
export const useReducerContext = () => {
const value = useContext(ReducerContext);
if (typeof value === 'string') {
throw new Error("Don't forget to render a <ReducerProvider> higher up the tree")
}
return value;
}
// used like:
const { state, dispatch } = useReducerContext();
另一种选择是更改 ReducerContext 的类型,使其仅使用 ContextProviderType
,而不是 string
。这确实意味着您需要提供完整的默认值:
export const ReducerContext = React.createContext<ContextProviderType>({
state: {
// Fill out an entire fake state object here
},
dispatch: () => {}
});
创建一个永远不会被使用的默认值可能会很痛苦,因此您可以使用类型断言来关闭打字稿:
export const ReducerContext = React.createContext<ContextProviderType>(
{} as ContextProviderType
)
我正在使用 useContext 和 useReducer 来管理应用程序状态。
以下是片段:
//ReducerProvider.tsx
type ContextProviderType = {
state: StateInterface,
dispatch: React.Dispatch<ActionInterface>
}
type CreateContextType = ContextProviderType | string; // i am passing to the createContext either the ContextProviderType or a string (the string is just to initialize without errors since useReducer is not declared yet)
export const ReducerContext = React.createContext<CreateContextType>('');
interface ProviderProps {
children: ReactNode
}
export const ReducerProvider: React.FC<ProviderProps> = ({children}): JSX.Element => {
const [state, dispatch] = useReducer(reducer, initialState);
return <>
<ReducerContext.Provider value={{state, dispatch}}>
{children}
</ReducerContext.Provider>
</>
}
//App.tsx
const App: React.FC = (): JSX.Element => {
return <>
<ReducerProvider>
//components here so they can take the value of the provider component
</ReducerProvider>
</>;
}
只有当我尝试获取状态和分派值时才会出现错误,如下所示:
//Component.tsx
export const Component: React.FC = (): JSX.Element => {
const { state, dispatch } = useContext(ReducerContext)
//ERROR: Property 'state' does not exist on type 'CreateContextType'
//ERROR: Property 'dispatch' does not exist on type 'CreateContextType'
return (
<div className="box">
//...
</div>
)
}
但我不理解这个错误,因为我声明 CreateContextType 可以是字符串或 ContextProviderType,它是一个接收状态和调度参数的对象。
But I'm not understanding this error since I declared that CreateContextType can be either a string or a ContextProviderType,
这正是您收到错误的原因:您说它可能是一个字符串。如果它是一个字符串,那么它不会有 state
和 dispatch
属性。由于它可能没有这些属性,TypeScript 不会让您访问它们,除非您编写代码以确保它们首先存在。
检查字符串可能如下所示:
let state;
let dispatch;
const value = useContext(ReducerContext);
if (typeof value === 'string') {
throw new Error('Uh oh, i got a string');
} else {
({ state, dispatch }) = value;
}
这显然很麻烦,因此您可以将此检查提取到自定义挂钩中:
export const useReducerContext = () => {
const value = useContext(ReducerContext);
if (typeof value === 'string') {
throw new Error("Don't forget to render a <ReducerProvider> higher up the tree")
}
return value;
}
// used like:
const { state, dispatch } = useReducerContext();
另一种选择是更改 ReducerContext 的类型,使其仅使用 ContextProviderType
,而不是 string
。这确实意味着您需要提供完整的默认值:
export const ReducerContext = React.createContext<ContextProviderType>({
state: {
// Fill out an entire fake state object here
},
dispatch: () => {}
});
创建一个永远不会被使用的默认值可能会很痛苦,因此您可以使用类型断言来关闭打字稿:
export const ReducerContext = React.createContext<ContextProviderType>(
{} as ContextProviderType
)