useReducer hook, ¿cómo se escribe comprobar la acción?

Sep 20 2020

He estado buscando en varios recursos aquí en stackoverflow y no he encontrado nada (todavía) que solucione este problema que tengo. Tengo un conocimiento básico de mecanografiado, por lo que los errores me han limitado.

Si lo dejo action: anyen mi reductor, el error desaparece. Sin embargo, si lo escribo con Action, obtengo un error de sobrecarga. Todavía no soy lo suficientemente inteligente con TS para descubrir cómo razonar sobre esto o resolverlo, está pasando ReducerWithoutAction<any>, pero no tengo idea de cómo se supone que debo solucionarlo. Cualquier ayuda sería apreciada.

Voy a seguir husmeando mientras tanto.

// state types
type MainWrapperType = {
  selection: number;
};

type Word = {
  word: string;
  translation: string;
  wordTranscription: string;
  partOfSpeech: string;
  description: string;
  example?: string;
};

type Notification = {
  format: string;
  message: string;
};

type Content = {
  lessonName: string;
  language: string;
  topics: string[];
  format: string;
  file: File;
};

type InitialState = {
  activeStep: number;
  notification: Notification;
  content: Content;
  newWords: Word[];
  initialTranscript: string;
  modifiedTranscript: string;
  transcriptSentences: string[];
};

const initialState = {
  activeStep: 0,
  notification: {
    format: "",
    message: "",
  },
  content: {
    lessonName: "",
    language: "",
    topics: [],
    format: "",
    file: "",
  },
  newWords: [],
  initialTranscript: "",
  modifiedTranscript: "",
  transcriptSentences: [],
};

// action types
interface SET_FILE {
  type: "SET_FILE";
  payload: File;
}

interface RESET_FILE {
  type: "RESET_FILE";
}

interface SET_INIT_TRANSCRIPT {
  type: "SET_INIT_TRANSCRIPT";
  payload: string;
}

interface SET_MODIFIED_TRANSCRIPT {
  type: "SET_MODIFIED_TRANSCRIPT";
  payload: string;
}

interface ADD_SENTENCE {
  type: "ADD_SENTENCE";
  payload: string;
}

interface SET_SENTENCE_TRANSLATIONS {
  type: "SET_SENTENCE_TRANSLATIONS";
  payload: string[];
}

interface ADD_NEW_WORD {
  type: "ADD_NEW_WORD";
  payload: Word;
}

interface UPDATE_WORD {
  type: "UPDATE_WORD";
  payload: Word;
}

interface INCREMENT_ACTIVE_STEP {
  type: "INCREMENT_ACTIVE_STEP";
}

interface DECREMENT_ACTIVE_STEP {
  type: "DECREMENT_ACTIVE_STEP";
}

interface RESET_ACTIVE_STEP {
  type: "RESET_ACTIVE_STEP";
}

interface RENDER_NOTIFICATION {
  type: "RENDER_NOTIFICATION";
  payload: Notification;
}

type Action =
  | SET_FILE
  | RESET_FILE
  | SET_INIT_TRANSCRIPT
  | SET_MODIFIED_TRANSCRIPT
  | ADD_SENTENCE
  | SET_SENTENCE_TRANSLATIONS
  | ADD_NEW_WORD
  | UPDATE_WORD
  | INCREMENT_ACTIVE_STEP
  | DECREMENT_ACTIVE_STEP
  | RESET_ACTIVE_STEP
  | RENDER_NOTIFICATION;

const reducer = (state: InitialState, action: Action) => {
  switch (action.type) {
    case "SET_FILE":
      return { ...state, content: action.payload };
    case "RESET_FILE":
      return { ...state, content: initialState.content };
    case "SET_INIT_TRANSCRIPT":
      return { ...state, initialTranscript: action.payload };
    case "SET_MODIFIED_TRANSCRIPT":
      return { ...state, modifiedTranscript: action.payload };
    case "ADD_SENTENCE":
      return {
        ...state,
        transcriptSentences: [...state.transcriptSentences, action.payload],
      };
    case "SET_SENTENCE_TRANSLATIONS":
      return {
        ...state,
        transcriptSentences: action.payload,
      };
    case "ADD_NEW_WORD":
      return {
        ...state,
        newWords: [...state.newWords, action.payload],
      };
    case "UPDATE_WORD":
      const newWordsClone = [...state.newWords];
      // console.log("nwc", newWordsClone);
      const seekWord = (wordObject: any) =>
        wordObject.word === action.payload.word;
      const wordIndex = newWordsClone.findIndex(seekWord);
      // console.log("wi", wordIndex, newWordsClone[wordIndex]);
      newWordsClone[wordIndex] = action.payload;
      return {
        ...state,
        newWords: newWordsClone,
      };
    case "INCREMENT_ACTIVE_STEP": {
      return { ...state, activeStep: state.activeStep + 1 };
    }
    case "DECREMENT_ACTIVE_STEP": {
      return { ...state, activeStep: state.activeStep - 1 };
    }
    case "RESET_ACTIVE_STEP": {
      return { ...state, activeStep: 0 };
    }
    case "RENDER_NOTIFICATION":
      return { ...state, notification: action.payload };
    default:
      throw new Error();
  }
};

const UploadPage = () => {
  const [state, dispatch] = useReducer(reducer, initialState); <-- Error
  ...
}

Respuestas

2 NearHuscarl Sep 21 2020 at 04:45

En su initialState, content.filese establece en una cadena vacía, pero debería estar Fileen su lugar

type Content = {
  file: File;
  ...
};

type InitialState = {
  content: Content;
  ...
};


const initialState = {
  content: {
    file: "",
  },
  ...
};

Puede solucionarlo inicializando un objeto nulo con el tipo correspondiente

const EMPTY_FILE = Object.freeze(new File([""], "filename"));
const initialState = {
  content: {
    file: EMPTY_FILE,
  },
  ...
};

También hay un pequeño error en su reductor.

switch (action.type) {
  case "SET_FILE":
    return { ...state, content: action.payload };
  ...
}

Debería ser esto

switch (action.type) {
  case "SET_FILE":
    return { ...state, content: { ...state.content, file: action.payload } };
  ...
}