如何为以下 contextapi 代码的 useReducer useContext 设置 Typescript 类型?

Posted

技术标签:

【中文标题】如何为以下 contextapi 代码的 useReducer useContext 设置 Typescript 类型?【英文标题】:How do I set Typescript types for useReducer useContext for the following contextapi code? 【发布时间】:2020-10-26 02:48:03 【问题描述】:

我想在下面的代码中使用正确的 TS 类型,而不是任何类型。我是反应 TS 的新手,请帮助...

如何为以下上下文 API 代码的 useReducer useContext 设置 typescript 类型:

import React, createContext, Dispatch from 'react';
import firebaseUser from '../@types/User';

interface Actions 
  SET_IMAGENAME: string;
  SET_USER: string;


export const Actions: Actions = 
  SET_IMAGENAME: 'SET_IMAGENAME',
  SET_USER: 'SET_USER',
;

function action(type: string) 
  return type;


function actionPayload(type: string, payload: any)  //here
  return type, payload;


export const Dispatches = 
  setImageName: action,
  setUser: actionPayload,
;

interface State 
  imgName: string;
  user: firebaseUser;


const initialState = 
  imgName: '',
  user:  as firebaseUser,
;

function reducer(state = initialState, action: type: string; payload: any)  //here
  switch (action.type) 
    case Actions.SET_IMAGENAME:
      return ...state, imgName: 'sample image';
    case Actions.SET_USER:
      return ...state, user: action.payload;
    default:
      return state;
  


export const Store = createContext<
  state: State;
  dispatch: Dispatch<any>; //here
>(
  state: initialState,
  dispatch: () => null,
);

export function StoreProvider(children: JSX.ElementChildrenAttribute): JSX.Element 
  const [state, dispatch] = React.useReducer(reducer, initialState);
  return <Store.Provider value=state, dispatch>children</Store.Provider>;

任何人都可以帮助我吗?不胜感激?

谢谢

【问题讨论】:

【参考方案1】:

我希望这个解决方案能给你一个好主意。

https://gist.github.com/sw-yx/f18fe6dd4c43fddb3a4971e80114a052

https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/context/#extended-example

export function createCtx<StateType, ActionType>(
  reducer: React.Reducer<StateType, ActionType>,
  initialState: StateType,
) 
  const defaultDispatch: React.Dispatch<ActionType> = () => initialState // we never actually use this
  const ctx = React.createContext(
    state: initialState,
    dispatch: defaultDispatch, // just to mock out the dispatch type and make it not optioanl
  )
  function Provider(props: React.PropsWithChildren<>) 
    const [state, dispatch] = React.useReducer<React.Reducer<StateType, ActionType>>(reducer, initialState)
    return <ctx.Provider value= state, dispatch  ...props />
  
  return [ctx, Provider] as const

// usage
const initialState =  count: 0 
type AppState = typeof initialState
type Action =
  |  type: 'increment' 
  |  type: 'add'; payload: number 
  |  type: 'minus'; payload: number 
  |  type: 'decrement' 

function reducer(state: AppState, action: Action): AppState 
  switch (action.type) 
    case 'increment':
      return  count: state.count + 1 
    case 'decrement':
      return  count: state.count - 1 
    case 'add':
      return  count: state.count + action.payload 
    case 'minus':
      return  count: state.count - action.payload 
    default:
      throw new Error()
  

const [ctx, CountProvider] = createCtx(reducer, initialState)
export const CountContext = ctx

// top level example usage
export function App() 
  return (
    <CountProvider>
      <Counter />
    </CountProvider>
  )


// example usage inside a component
function Counter() 
  const  state, dispatch  = React.useContext(CountContext)
  return (
    <div>
      Count: state.count
      <button onClick=() => dispatch( type: 'increment' )>+</button>
      <button onClick=() => dispatch( type: 'add', payload: 5 )>+5</button>
      <button onClick=() => dispatch( type: 'decrement' )>-</button>
      <button onClick=() => dispatch( type: 'minus', payload: 5 )>+5</button>
    </div>
  )

【讨论】:

【参考方案2】:

这真的取决于有效负载可以包含什么,它可以包含图像或 FirebaseUser 实例的字符串,您可以设置payload: string | FirebaseUser

import React, createContext, Dispatch from 'react';
import firebaseUser from '../@types/User';

interface Actions 
  SET_IMAGENAME: string;
  SET_USER: string;


export const Actions: Actions = 
  SET_IMAGENAME: 'SET_IMAGENAME',
  SET_USER: 'SET_USER',
;

function action(type: string) 
  return type;


// If payload can contain string of image or FirebaseUser instance
// it will be string | FirebaseUser
// if payload will only contain FirebaseUser instance you just need payload: FirebaseUser
export type ActionType = 
 type: string,
 payload: string | FirebaseUser


// If payload can contain string of image or FirebaseUser instance
// it will be string | FirebaseUser
// if payload will only contain FirebaseUser instance you just need payload: FirebaseUser
function actionPayload(type: string, payload: string | FirebaseUser )  //here
  return type, payload;


export const Dispatches = 
  setImageName: action,
  setUser: actionPayload,
;

interface State 
  imgName: string;
  user: FirebaseUser;


const initialState = 
  imgName: '',
  user:  as firebaseUser,
;

// set Action type here
function reducer(state = initialState, action: ActionType) 
  switch (action.type) 
    case Actions.SET_IMAGENAME:
      // need to cast type herer
      return ...state, imgName: action.payload as string;
    case Actions.SET_USER:
      // need to cast type herer
      return ...state, user: action.payload as firebaseUser;
    default:
      return state;
  


export const Store = createContext<
  state: State;
  dispatch: Dispatch<ActionType>; //action type here
>(
  state: initialState,
  dispatch: () => null,
);

export function StoreProvider(children: JSX.ElementChildrenAttribute): JSX.Element 
  const [state, dispatch] = React.useReducer(reducer, initialState);
  return <Store.Provider value=state, dispatch>children</Store.Provider>;

【讨论】:

感谢您抽出时间来帮助我,最后一行的状态仍然出错,您可以检查一下吗?这是链接:codesandbox.io/s/boring-ramanujan-jtrb3?file=/src/… @Sushilzzz 我们也需要在减速器中设置状态时进行强制转换。请检查:codesandbox.io/s/affectionate-mendel-19ev9?file=/src/…【参考方案3】:

这也是我的解决方案,通过添加类型文件来更清洁您的文件结构,我希望您觉得它有用: myCodesandboxRepo

【讨论】:

以上是关于如何为以下 contextapi 代码的 useReducer useContext 设置 Typescript 类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Spring Security 创建类型安全的用户角色?

如何为以下示例创建自定义格式、公式或 VBA 代码?

如何为属性定义别名

如何为以下异常处理代码编写junit测试用例?

如何为以下代码设置优先级高精度位置

如何为登录GRAILS(Spring security)的用户实现会话?