为包装 <App/> 的上下文提供程序键入道具?
Type props for a context provider wrapping <App/>?
我正在定义一个上下文提供程序来包装我的 <App/>
组件,如下所示:
// index.ts
ReactDOM.render(
<ApolloProvider client={client}>
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>
</ApolloProvider>,
document.getElementById('root')
);
我通过传递从 React.ReactNode
类型的 props 解构的 {children}
使上下文提供程序定义工作,并且 return 将子项包装在两个 <AuthContext.Provider>
标签之间,例如这个:
// src/context/AutContext.ts
// Context definition
const AuthContext = React.createContext<{currentUser: User} | undefined>(undefined);
// Context provider wrapper definition:
const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const { currentUser } = useCurrentUse();
return (
<AuthContext.Provider value={{ currentUser }}>
{children} // <- note the different ways of passing children to the Provider
</AuthContext.Provider>
);
};
但我正在尝试通过将 <AuthContext.Provider/>
减少为一行来简化代码,现在我正在努力定期传递 props
,但类型为 any
:
// Context provider wrapper definition (one liner variant):
const AuthProvider = (props: any) => { // <- any type. props instead of destructured {children}
const { currentUser } = useCurrentUser();
return <AuthContext.Provider value={{ currentUser }} {...props} />; // <- spread one liner
};
知道我应该如何在第二个变体中输入 props
吗?我试过推断它,但结果不起作用(而且一团糟),并且使用 React.ReactNode
作为类型仅适用于 {children}
,不适用于整个 props
.
在 @types/react
中我找到了一个 ProviderProps<T>
可能是解决方案,但如果是,我仍然不知道用什么替换 T
。
查看 type definition 的 ProviderProps<T>
通用 T
用于键入 value
属性。
这意味着您将提供与 React.createContext<T>()
相同的 T
。
简单方法:
// We know from inspecting the ProviderProps type that it has two properties
// The first property value is not to be passed in.
// The second property children is an optional set of react nodes.
// The React.FunctionComponent type with no generic added only has a prop of type
// children?: React.ReactNode.
// This will make the props of AuthProvider compatible with the props of AuthContext.Provider.
const AuthProvider: React.FunctionComponent = (props) => {
const { currentUser } = useCurrentUser();
return (
<AuthContext.Provider value={{ currentUser }} {...props} />
);
};
更复杂的方法:
type ContextValue = {currentUser: User} | undefined;
// depending on your version of typescript Omit might not like types with generics
// the work around for this is to create a wrapping type around Omit to trick it into
// thinking that it is getting a type it approves of.
// If this does not effect your version of typescript just use:
// Omit<ProviderProps<ContextValue>, 'value'>
type OmitValue<T> = Omit<T, 'value'>
const AuthContext = React.createContext<ContextValue>(undefined);
// We do not control the type ProviderProps, this may change in the future.
// To give better future proofing we can use the ProviderProp type and remove the
// properties we do not want to be changed (value in this case) using Omit.
// This means that any additional properties added to ProviderProps in the future
// will be valid for AuthProvider, but at this point in time it will just be
// children.
const AuthProvider: React.FunctionComponent<OmitValue<ProviderProps<ContextValue>>> = (props) => {
const { currentUser } = useCurrentUser();
return (
<AuthContext.Provider value={{ currentUser }} {...props} />
);
};
我正在定义一个上下文提供程序来包装我的 <App/>
组件,如下所示:
// index.ts
ReactDOM.render(
<ApolloProvider client={client}>
<React.StrictMode>
<AuthProvider>
<App />
</AuthProvider>
</React.StrictMode>
</ApolloProvider>,
document.getElementById('root')
);
我通过传递从 React.ReactNode
类型的 props 解构的 {children}
使上下文提供程序定义工作,并且 return 将子项包装在两个 <AuthContext.Provider>
标签之间,例如这个:
// src/context/AutContext.ts
// Context definition
const AuthContext = React.createContext<{currentUser: User} | undefined>(undefined);
// Context provider wrapper definition:
const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const { currentUser } = useCurrentUse();
return (
<AuthContext.Provider value={{ currentUser }}>
{children} // <- note the different ways of passing children to the Provider
</AuthContext.Provider>
);
};
但我正在尝试通过将 <AuthContext.Provider/>
减少为一行来简化代码,现在我正在努力定期传递 props
,但类型为 any
:
// Context provider wrapper definition (one liner variant):
const AuthProvider = (props: any) => { // <- any type. props instead of destructured {children}
const { currentUser } = useCurrentUser();
return <AuthContext.Provider value={{ currentUser }} {...props} />; // <- spread one liner
};
知道我应该如何在第二个变体中输入 props
吗?我试过推断它,但结果不起作用(而且一团糟),并且使用 React.ReactNode
作为类型仅适用于 {children}
,不适用于整个 props
.
在 @types/react
中我找到了一个 ProviderProps<T>
可能是解决方案,但如果是,我仍然不知道用什么替换 T
。
查看 type definition 的 ProviderProps<T>
通用 T
用于键入 value
属性。
这意味着您将提供与 React.createContext<T>()
相同的 T
。
简单方法:
// We know from inspecting the ProviderProps type that it has two properties
// The first property value is not to be passed in.
// The second property children is an optional set of react nodes.
// The React.FunctionComponent type with no generic added only has a prop of type
// children?: React.ReactNode.
// This will make the props of AuthProvider compatible with the props of AuthContext.Provider.
const AuthProvider: React.FunctionComponent = (props) => {
const { currentUser } = useCurrentUser();
return (
<AuthContext.Provider value={{ currentUser }} {...props} />
);
};
更复杂的方法:
type ContextValue = {currentUser: User} | undefined;
// depending on your version of typescript Omit might not like types with generics
// the work around for this is to create a wrapping type around Omit to trick it into
// thinking that it is getting a type it approves of.
// If this does not effect your version of typescript just use:
// Omit<ProviderProps<ContextValue>, 'value'>
type OmitValue<T> = Omit<T, 'value'>
const AuthContext = React.createContext<ContextValue>(undefined);
// We do not control the type ProviderProps, this may change in the future.
// To give better future proofing we can use the ProviderProp type and remove the
// properties we do not want to be changed (value in this case) using Omit.
// This means that any additional properties added to ProviderProps in the future
// will be valid for AuthProvider, but at this point in time it will just be
// children.
const AuthProvider: React.FunctionComponent<OmitValue<ProviderProps<ContextValue>>> = (props) => {
const { currentUser } = useCurrentUser();
return (
<AuthContext.Provider value={{ currentUser }} {...props} />
);
};