首页 > 解决方案 > 离子反应类型不可分配

问题描述

我正在使用带有以下代码的离子反应及其给出错误

类型'{状态:IState; 调度:React.Dispatch;}' 不可分配给类型 'IState'。对象字面量只能指定已知属性,而“IState”类型中不存在“状态”。

代码如下所示

状态.tsx

import React from "react";

export interface IState {
    count: number;
    loggedIn: boolean;
  }

// set the initial values
const initialState = { count: 0, loggedIn: false };

export type ActionType =
  | { type: "setLoggedIn"; payload: any }
  | { type: "error" };


// create the context
export const Context = React.createContext<IState>(initialState);

export const TheProvider = ({ children }: any): any => {
    /**
     * @param {*} state
     * @param {*} action
     */
    const reducer = (state: IState, action: ActionType): IState => {
      switch (action.type) {
        case "setLoggedIn":
          return { ...state, ...action.payload };
        default:
          throw new Error();
      }
    };
  
    const [state, dispatch] = React.useReducer(reducer, initialState);
  
    // wrap the application in the provider with the initialized context
    return (
      <Context.Provider value={{ state, dispatch }}>{children}</Context.Provider>
    );
  };
  
  export default Context;

登录.tsx

import AppContext, { TheProvider, IState }  from './State'; 


...

const Login: React.FC = () => {
    const { state, dispatch } = React.useContext<any>(AppContext);
  

    const doLogin = async () => {

        try{
          
           dispatch({
                type: 'setLoggedIn',
                payload: {loggedIn: false}
            })

        }catch(err){
          console.error("failed to login with erro", err)
        }
      };

    return (
 <TheProvider>
        <form className="ion-padding">
        <IonToolbar>
          <IonTitle>Login</IonTitle>
        </IonToolbar>
          <IonItem style={{paddingTop:'100px'}}>
            <IonLabel position="floating">Email</IonLabel>
            <IonInput type="email" value={email} onIonChange={e => setEmail(e.detail.value!)}/>
          </IonItem>
          <IonItem>
            <IonLabel position="floating">Password</IonLabel>
            <IonInput type="password" value={password} onIonChange={e => setPassword(e.detail.value!)}/>
          </IonItem>
          <IonItem>
            <IonLabel>{errMessage}</IonLabel>
          </IonItem>
          
          <IonButton className="ion-margin-top" onClick={doLogin} expand="block">
            <IonIcon slot="start" icon={mailOutline} />Login
          </IonButton>
        </form>
        </TheProvider>
    )
};

我现在在调度时遇到错误

TypeError: dispatch is not a function at doLogin

标签: reactjsionic-frameworkionic-react

解决方案


问题在于这两行之间的差异:

export const Context = React.createContext<IState>(initialState);
// ...
<Context.Provider value={{ state, dispatch }}>

如果您希望您的上下文包括状态以及调度,您需要将您的初始Context对象更改为如下内容:

interface ContextType {
    state: IState,
    dispatch?: React.Dispatch<ActionType>
  }
export const Context = React.createContext<ContextType>({ state: initialState });

在您的调用中useContext,您可以删除通用的<any>. 然后您可能需要检查dispatch已定义,因为它在ContextType上面设置为可选:

import AppContext, { TheProvider }  from './State'; 

// ...

const Login = () => {
  const { state, dispatch } = React.useContext(AppContext);

  const doLogin = async () => {
    if (dispatch === undefined) {
      return; // or display error message
    }
    try {
      dispatch({
        type: "setLoggedIn",
        payload: { loggedIn: false },
      });
    } catch (err) {
      console.error("failed to login with error:", err);
    }
  };

  return <div id="login"></div>; // presumably this holds your inputs, 
                                 // submit button, forgot password link, etc.
}

然后,要确保正确传递上下文,您必须确保Login它是TheProvider. 在同一个Login.tsx文件中,您可以LoginPage像这样定义一个新组件,如果您有一个Layout包含页眉、页脚、CSS 等的组件:

const LoginPage = () => {
  return <TheProvider>
           <Layout>
             <h2>Please enter your information below to log in:</h2>
             <Login />
           </Layout>
         </TheProvider>
}

推荐阅读