如何为以下 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 类型?的主要内容,如果未能解决你的问题,请参考以下文章