用usecontext在typeScript中使用

发布于 2025-02-03 00:49:36 字数 1159 浏览 4 评论 0原文

可以说,我有一个基本设置用于检查用户是否已登录:

import { createContext } from "react";
const UserContext = createContext<string | null>(null)
export default UserContext

在我的app.tsx中,我想创建一个usestate钩子,以便我可以在整个应用程序中管理上下文的状态:

//Context
const [context, setContext] = useState<string | null>(null)

  <UserContext.Provider value={{context, setContext}}>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </UserContext.Provider>

所以尽我所能看到我只需要登录用户的名称,或者如果我想拒绝访问某些页面,则将上下文的状态设置为null。现在的问题是,Typescript在这里对我大喊大叫,特别是在提供商的价值上:

Type '{ context: string | null; setContext: 
React.Dispatch<React.SetStateAction<string | null>>; }' is not assignable to type 'string'.ts(2322)

我可以强迫以下值施放值:

value={{context, setContext} as any}

但这似乎不是一个特别优雅的“ typescripty”解决方案。

任何帮助都将受到赞赏!

Lets say I have a basic setup for checking whether a user is logged in or not:

import { createContext } from "react";
const UserContext = createContext<string | null>(null)
export default UserContext

In my App.tsx I want to create a useState hook so that I can manage the state of my context throughout my application:

//Context
const [context, setContext] = useState<string | null>(null)

  <UserContext.Provider value={{context, setContext}}>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </UserContext.Provider>

So as far as I can see I'll only ever need either the name of the logged in user, or set the state of the context to null if I want to deny access to certain pages. Now the issue is that typescript is yelling at me here, specifically in the value of the Provider:

Type '{ context: string | null; setContext: 
React.Dispatch<React.SetStateAction<string | null>>; }' is not assignable to type 'string'.ts(2322)

I can force cast the value as follows:

value={{context, setContext} as any}

But that doesn't seem like a particularly elegant 'typescripty' solution.

Any help is appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我很OK 2025-02-10 00:49:36

根据亚历克斯的回答,我提出了一项对我有用的调整:

type UserContextType = {
     context: string | null,
     setContext: React.Dispatch<React.SetStateAction<string | null>>
 }

const iUserContextState = {
    context: null,
    setContext: () => {}
}

const UserContext = createContext<UserContextType>(iUserContextState)

export default UserContext

然后在app.tsx中:

//Context
const [context, setContext] = useState<string | null>(null)

  <UserContext.Provider value={{context, setContext}}>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </UserContext.Provider>

Based on Alex's answer I came up with a tweak that works for me:

type UserContextType = {
     context: string | null,
     setContext: React.Dispatch<React.SetStateAction<string | null>>
 }

const iUserContextState = {
    context: null,
    setContext: () => {}
}

const UserContext = createContext<UserContextType>(iUserContextState)

export default UserContext

And then in App.tsx:

//Context
const [context, setContext] = useState<string | null>(null)

  <UserContext.Provider value={{context, setContext}}>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </UserContext.Provider>
初吻给了烟 2025-02-10 00:49:36

您已经将上下文键入:

string | null

但是,但是您为(近似)类型的上下文提供了一个值:

{ context: string | null, setContext: (newString) => void }

因此,如果您希望状态设置器在上下文中,那么它需要成为上下文类型的一部分:

const UserContext = createContext<{
  context: string | null,
  setContext: (newValue) => void
}>({
  context: null,
  setContext: () => undefined
})

You've typed your context as:

string | null

But then you provide a value for that context of (approxiamately) type:

{ context: string | null, setContext: (newString) => void }

So if you want the state setter in your context, then it needs to be part of the context's type:

const UserContext = createContext<{
  context: string | null,
  setContext: (newValue) => void
}>({
  context: null,
  setContext: () => undefined
})
豆芽 2025-02-10 00:49:36

如果要将usestate的数组作为返回值,这是一个正确的打字稿解决方案:

import React, { FC, createContext, useContext, useState } from 'react';

// Change shape of this object to your/app needs
const initialAppState = {
  userName: "",
};

export type AppState = typeof initialAppState;

type ContextType = [AppState, React.Dispatch<React.SetStateAction<AppState>>];
const AppStateContext = createContext<ContextType>([] as unknown as ContextType);

type Props = {
  appState?: AppState;
};

/**
 * Provider to pass state to the React application
 */
export const AppStateProvider: FC<React.PropsWithChildren<Props>> = (props) => {
  const { appState = null } = props;
  const useStateRetValue = useState<AppState>(appState == null ? initialAppState : appState);

  return <AppStateContext.Provider value={useStateRetValue}>{props.children}</AppStateContext.Provider>;
};
AppStateProvider.defaultProps = {
  appState: undefined,
};

/**
 * Hook to access application state
 */
export const useAppStateContext = (): ContextType => useContext<ContextType>(AppStateContext);

提供商用法:

  <AppStateProvider>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </AppStateProvider>

挂钩使用:


const [appState, setAppState] = useAppStateContext();

console.log(appState.userName);

useEffect(() => {
  setAppState({ userName: "John Doe" });
}, [setAppState]);

// ...or...

const [, setAppState] = useAppStateContext();

// ...or...

const [appState] = useAppStateContext();

If you want to keep the useState's array as a return value, this is a correctly TypeScript solution:

import React, { FC, createContext, useContext, useState } from 'react';

// Change shape of this object to your/app needs
const initialAppState = {
  userName: "",
};

export type AppState = typeof initialAppState;

type ContextType = [AppState, React.Dispatch<React.SetStateAction<AppState>>];
const AppStateContext = createContext<ContextType>([] as unknown as ContextType);

type Props = {
  appState?: AppState;
};

/**
 * Provider to pass state to the React application
 */
export const AppStateProvider: FC<React.PropsWithChildren<Props>> = (props) => {
  const { appState = null } = props;
  const useStateRetValue = useState<AppState>(appState == null ? initialAppState : appState);

  return <AppStateContext.Provider value={useStateRetValue}>{props.children}</AppStateContext.Provider>;
};
AppStateProvider.defaultProps = {
  appState: undefined,
};

/**
 * Hook to access application state
 */
export const useAppStateContext = (): ContextType => useContext<ContextType>(AppStateContext);

Provider usage:

  <AppStateProvider>

    <Routes>

      <Route path="/" element={<Home/>}/> 
      <Route path="/login" element={<Login/>}/> 
      <Route path="/register" element={<Register/>}/> 
      <Route path="/admin" element={<Admin/>}></Route>

    </Routes>  

  </AppStateProvider>

Hook usage:


const [appState, setAppState] = useAppStateContext();

console.log(appState.userName);

useEffect(() => {
  setAppState({ userName: "John Doe" });
}, [setAppState]);

// ...or...

const [, setAppState] = useAppStateContext();

// ...or...

const [appState] = useAppStateContext();

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文