reactjs - Typen '{}' saknar följande egenskaper från typen - TS-fel


I returvärdet av useUser()-funktionen får jag hela tiden detta TypeScript-fel.

Typen '{}' saknar följande egenskaper från typ 'IUseUser': userState, dispatchUserContext

import { useReducer, useContext, createContext, FunctionComponent } from 'react';

export interface EditProfileFields {
  phone: string;
  city: string;
  description: string;
  startDate: string;
  endDate: string;
  priceRate: string;
}

export interface IUserContext extends EditProfileFields {
  coverImg: string;
  profileImg: string;
  isDogSitter: boolean;
  isAvailable: boolean;
}

type Action =
  | { type: 'UPLOAD_PROFILE'; profileImg: string }
  | { type: 'UPLOAD_BACKGROUND'; coverImg: string }
  | { type: 'EMPTY_IMAGES' }
  | { type: 'SET_IS_DOG_SITTER' }
  | { type: 'UPDATE_EDIT_PROFILE_FIELDS'; fields: EditProfileFields };

type Dispatch = (action: Action) => void;

export interface IUseUser {
  userState: IUserContext;
  dispatchUserContext: Dispatch;
}

const userReducer = (state: IUserContext, action: Action) => {
  switch (action.type) {
    case 'UPLOAD_PROFILE':
      return { ...state, profileImg: action.profileImg };
    case 'UPLOAD_BACKGROUND':
      return { ...state, coverImg: action.coverImg };
    case 'EMPTY_IMAGES':
      return { ...state, coverImg: '', profileImg: '' };
    case 'SET_IS_DOG_SITTER':
      return { ...state, isDogSitter: true };
    case 'UPDATE_EDIT_PROFILE_FIELDS':
      const { startDate, endDate, ...otherFields } = action.fields;
      return {
        ...state,
        startDate: startDate !== null ? startDate.substring(0, 10) : '',
        endDate: endDate !== null ? endDate.substring(0, 10) : '',
        ...otherFields,
      };
    default:
      throw new Error();
  }
};

const UserContext = createContext({});

const UserProvider: FunctionComponent = ({ children }): JSX.Element => {
  const [userState, dispatchUserContext] = useReducer(userReducer, {
    coverImg: '',
    profileImg: '',
    isDogSitter: false,
    isAvailable: false,
    phone: '',
    city: '',
    description: '',
    startDate: '',
    endDate: '',
    priceRate: '',
  });
  return <UserContext.Provider value={{ userState, dispatchUserContext }}>{children}</UserContext.Provider>;
};

function useUser(): IUseUser {
  const context = useContext(UserContext);
  if (context === undefined) {
    throw new Error('useUser must be used within a UserProvider');
  }
  return context;
}

export { UserProvider, useUser };

Svar #1

Den enkla lösningen för att göra nycklarna i IUseUser valfria.

export interface IUseUser {
  userState?: IUserContext;
  dispatchUserContext?: Dispatch;
}

Men varför står det som tomt {}? Svaret är att du skapar ett sammanhang med ett tomt objektvärde. Så ditt standardvärde är ett tomt objekt. Du behöver ge standardvärden till det sammanhanget. Då behöver du inte ge valfria nycklar.

const UserContext = createContext<IUseUser>({
  userState: {
    coverImg: '',
    profileImg: '',
    isDogSitter: false,
    isAvailable: false,
    phone: '',
    city: '',
    description: '',
    startDate: '',
    endDate: '',
    priceRate: '',
  },
  dispatchUserContext: (action: Action) => {},
});

Skicka inte ett tomt objekt som standardvärde till ditt sammanhang. Du kan antingen skicka undefined eller value.

Enligt den officiella dokumentationen för React,

"Argumentet defaultValue används endast när en komponent inte har en motsvarande Provider ovanför sig i trädet. Detta kan vara användbart för att testa komponenter isolerat utan att omsluta dem. Obs: att skicka undefined som ett Provider-värde gör inte att komponenterna som använder det använder defaultValue."

Om du vill ge ett odefinierat värde till ditt sammanhang kan du i TypeScript skapa ett sammanhang så här,

const UserContext = createContext<IUseUser | undefined>(undefined);

Relaterade artiklar