英文:
How to use typescript with createContext when passing state variables as the provider value?
问题
我正在尝试在使用 TypeScript 时使用 createContext。我正在创建一个名为 "NavContext" 的上下文包装类,并将状态变量作为值传递给提供程序。
以下是代码:
export const NavContext = createContext<any>();
const NavBar: React.FC<ReactNode | undefined> = ({ children }) => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}>
<AppBar position="static">{children}</AppBar>
</NavContext.Provider>
);
};
但我在 "createContext()" 下方得到了插入符号 "^^^^^^",并且收到了 TypeScript 错误消息:
TS2554: 期望 1 个参数,但得到 0 个。
请指导我如何解决此错误,因为在没有 TypeScript 的情况下,此代码运行正常。
英文:
I am trying to use typescript with createContext. I am making a context wrapper class NavContext
and passing state variables as value to the provider.
Here is the code:
export const NavContext = createContext();
const NavBar:ReactFC<ReactNode | undefined>= ({ children }) => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}>
<AppBar position="static">{children}</AppBar>
</NavContext.Provider>
);
};
But I get caret symbol ^^^^^^
beneath createContext()
and get typescript error as
TS2554: Expected 1 arguments, but got 0.
Please guide me on how to resolve this error as without typescript this code worked fine.
答案1
得分: 2
以下是您提供的代码的翻译部分:
设置 NavbarContext.tsx
:
type NavContextType = {
isDrawerOpen: boolean;
setIsDrawerOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
export const NavContext = createContext<NavContextType | null>(null);
type ProviderType = {
children: React.ReactNode;
};
export default function NavBarStateProvider({ children }: ProviderType) {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}>
{children}
</NavContext.Provider>
);
}
用于使用上下文的自定义钩子,useNavContext.tsx
:
export default function useNavContext() {
const context = useContext(NavContext);
if (!context) {
throw new Error("useNavContext must be used within a NavBarStateProvider");
}
return context;
}
请注意,这是您提供的代码的翻译部分,我没有提供其他内容。
英文:
This is the way I set up context with TS, by providing a default value:
Set up NavbarContext.tsx
:
type NavContextType = {
isDrawerOpen: boolean;
setIsDrawerOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
export const NavContext = createContext<NavContextType | null>(null);
type ProviderType = {
children: React.ReactNode;
};
export default function NavBarStateProvider({ children }: ProviderType) {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}>
{children}
</NavContext.Provider>
);
}
Custom hook to use the context, useNavContext.tsx
:
export default function useNavContext() {
const context = useContext(NavContext);
if (!context) {
throw new Error("useNavContext must be used within a NavBarStateProvider");
}
return context;
}
答案2
得分: 0
问题是上下文可能被消耗而不一定是 Provider 的子级。即使您的应用程序在任何地方都不这样做,您仍需要通过将默认上下文值传递给.createContext
来使 TypeScript 快乐(因为上下文值类型似乎具有其中的状态设置器,我会假设总会有一个提供者 - 因为您不能在 React 组件的上下文之外具有状态设置器。)
一种选择是向 createContext
传递一个无意义的参数(只是因为它是必需的),并告诉 TypeScript 类型不匹配是可以的。还要注意,createContext
也应该有一个泛型参数。
type NavContextType = {
isDrawerOpen: boolean;
setIsDrawerOpen: React.Dispatch<React.SetStateAction<boolean>>;
};
export const NavContext = createContext<NavContextType>(undefined!);
英文:
The problem is that contexts can be consumed without necessarily being a child of a Provider. Even if your app doesn't do this anywhere, you need to make TypeScript happy by passing the default context value to .createContext
. (Because the context value type looks to have a state setter in it, I'd assume that there will always be a provider - because you can't have a state setter outside the context of a React component.)
One option is to pass a meaningless argument to createContext
(just because it's required) and tell TypeScript that it's OK that the type doesn't match. Also note that createContext
should have a generic argument as well.
type NavContextType = {
isDrawerOpen: boolean;
setIsDrawerOpen: React.Dispatch<React.SetStateAction<boolean>>;
};
export const NavContext = createContext<NavContextType>(undefined!);
答案3
得分: 0
你应该清晰地定义 provider 和 context 的类型。
interface ProviderProps {
children: React.ReactNode
}
interface ContextValue {
isDrawerOpen: boolean;
setIsDrawerOpen: () => void;
}
export const NavContext = createContext<ContextValue>(
null as unknown as ContextValue
)
const NavBar = ({ children }: ProviderProps) => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}>
<AppBar position="static">{children}</AppBar>
</NavContext.Provider>
);
};
英文:
You should define the types for provider and context clearly.
interface ProviderProps {
children: React.ReactNode
}
interface ContextValue {
isDrawerOpen: boolean;
setIsDrawerOpen: () => void;
}
export const NavContext = createContext<ContextValue>(
null as unknown as ContextValue
)
const NavBar = ({ children }: ProviderProps) => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
return (
<NavContext.Provider value={{ isDrawerOpen, setIsDrawerOpen }}>
<AppBar position="static">{children}</AppBar>
</NavContext.Provider>
);
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论