简体   繁体   English

如何在Reducer中使用react动态设置state和initialState的类型?

[英]How can I set dynamicly type for state and initialState inReducer with react?

I have different types of response which I don't know exactly type is ,is that any way to change response type base on dispatch in component我有不同类型的响应,我不知道确切的类型是什么,是否可以根据组件中的调度更改响应类型

 export interface State { loading: boolean; response: FilteredDataType | Response | string | number,...'I dont know type' ???? error?: string; } export type Actions = | { type: 'SET_LOADING '; payload: boolean } | { type: 'SET_SUCCESS_SELECTED'; payload: Response } | { type: 'SET_SUCCESS'; payload: FilteredDataType } | { type: 'SET_FAILURE'; payload: string } export const initialState: State = { loading: false, response: ????, error: '', } export function reducer(prevState: State, action: Actions): State { switch (action.type) { case 'SET_LOADING ': return { ...prevState, loading: action.payload } case 'SET_SUCCESS': return { ...prevState, response: action.payload, loading: false } case 'SET_SUCCESS_SELECTED': return { ...prevState, response: action.payload, loading: false } case 'SET_FAILURE': return { ...prevState, loading: false, error: action.payload } default: return initialState } } const Selected: React.FunctionComponent<PropsType> = ({ date, from }) => { const { state: { session } } = useContext(SessionContext) const { selectedSpid } = useInfoState() const [state, dispatch] = useReducer(reducer, initialState); const load = useCallback(async () => { dispatch({ type: 'SET_LOADING ', payload: false }) try { if (date && date.length) { const response = await getData(date, date) const responseApi: DataResponse = response.data dispatch({ type: 'SET_SUCCESS_SELECTED', payload: responseApi }) dispatch({ type: 'SET_LOADING ', payload: true }) } } catch (e) { return dispatch({ type: 'SET_FAILURE', payload: e.Tostring() }) } }, []) useEffect(() => { if (session && selectedSpid) { load() } }, [date, from]) return ( <Spin spinning={!selectedSpid}> <Row> // Map has Error becuse of type {state.response && state.response.map((item) => <SelectedCard key={item.id} {...item} icon={true} /> )} </Row> </Spin> ) } export default Selected
 const Selected: React.FunctionComponent<PropsType> = ({ date, from }) => { const { state: { session } } = useContext(SessionContext) const { selectedSpid } = useInfoState() const [state, dispatch] = useReducer(reducer, initialState); const load = useCallback(async () => { dispatch({ type: 'SET_LOADING ', payload: false }) try { if (date && date.length) { const response = await getData(date, date) const responseApi: DataResponse = response.data dispatch({ type: 'SET_SUCCESS_SELECTED', payload: responseApi }) dispatch({ type: 'SET_LOADING ', payload: true }) } } catch (e) { return dispatch({ type: 'SET_FAILURE', payload: e.Tostring() }) } }, []) useEffect(() => { if (session && selectedSpid) { load() } }, [date, from]) return ( <Spin spinning={!selectedSpid}> <Row> // Map has Error becuse of type {state.response && state.response.map((item) => <SelectedCard key={item.id} {...item} icon={true} /> )} </Row> </Spin> ) } export default Selected

I am going to dispatch type of request base on a different type of request, I am going to know is that any way to change dynamically state base on the request?我将根据不同类型的请求调度请求类型,我将知道有什么方法可以根据请求动态更改状态?

is any one help me?有人帮我吗?

Based on your code sample, and where you put I don't know what type ;根据您的代码示例,以及您放在哪里, I don't know what type it sounds like you're trying to have the State.response type to be a union type of all possible payloads that an action might have.听起来您正试图让State.response类型成为操作可能具有的所有可能payloads的联合类型。 You can do this with a lookup type, as shown below.您可以使用查找类型执行此操作,如下所示。

export interface State {
    loading: boolean;
    response?: Actions["payload"];
    error?: string;
}

export type Actions =
    | { type: 'SET_LOADING '; payload: boolean }
    | { type: 'SET_SUCCESS_SELECTED'; payload: Response }
    | { type: 'SET_SUCCESS'; payload: FilteredDataType }
    | { type: 'SET_FAILURE'; payload: string }

export const initialState: State = {
    loading: false,
}

But you also said ...is that any way to change response type base on dispatch in component .但是您还说...is that any way to change response type base on dispatch in component Which sounds a bit like you don't want to have the Actions type at all.这听起来有点像您根本不想拥有Actions类型。 The actions type cannot be inferred from the usage of dispatch() so the only way to do that would be to have your useReducer take an any type for a second parameter.动作类型不能从dispatch()的使用中推断出来,所以唯一的方法是让你的useReducer为第二个参数采用any类型。 Then you would lose all the advantages of typescript in your reducer, which I really wouldn't recommend.然后你会在你的减速器中失去打字稿的所有优点,我真的不推荐。

I mean if you truly have no idea what the response will contain you can just use any , or if you know it will be some kind of object you can create a generic object type that will allow it to have anything as a key:我的意思是,如果您真的不知道响应将包含什么,您可以使用any ,或者如果您知道它将是某种对象,您可以创建一个通用对象类型,允许它以任何东西作为键:

type GenericObject = { [key: string]: any }

If it's just a certain number of potential types, you could create separate ones and use union types like you're already doing:如果它只是一定数量的潜在类型,您可以创建单独的类型并使用联合类型,就像您已经在做的那样:

type ResponseA = { something: string }
type ResponseB = { somethingElse: string }

...

export interface State {
    loading: boolean;
    response: ResponseA | ResponseB;
    error?: string;
}

You can't change the type of something in response to an action that occurs.您无法更改某物的类型以响应发生的操作。 TypeScript's type checking only occurs at compile time to enforce type safety during development. TypeScript 的类型检查仅在编译时进行,以在开发期间强制执行类型安全。 At runtime, all of the TypeScript is removed and compiled into regular JavaScript that can run in a browser/on a server.在运行时,所有的 TypeScript 都被删除并编译成可以在浏览器/服务器上运行的常规 JavaScript。 As long as the types you're using aren't throwing errors and are enforcing type safety to the level you need,只要您使用的类型没有抛出错误并且将类型安全强制到您需要的级别,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM