Необработанный отказ (ошибка типа): состояние.push не является функцией при использовании redux thunk

#reactjs #react-redux #redux-thunk

Вопрос:

Я получаю эту ошибку Необработанного отклонения (ошибка типа): state.push не является функцией при использовании redux thunk, но при повторном отображении страницы после ошибки в базу данных добавляется новое слово.

Ниже приведен мой код.

 import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";

export const getDictionaryAsync = createAsyncThunk(
  "dictionary/getDictAsync",
  async () => {
    let res = await fetch("https://vocabulary-app-be.herokuapp.com/dictionary");
    if (res.ok) {
      let dictData = await res.json();
      return { dictData };
    }
  }
);

export const addWordtoDictAsync = createAsyncThunk(
  "dictionary/addWordtoDictAsync",
  async (payload) => {
    let res = await fetch(
      "https://vocabulary-app-be.herokuapp.com/dictionary",
      {
        method: "POST",
        body: JSON.stringify({ word: payload.word }),
        headers: {
          "Content-Type": "application/json",
        },
      }
    );
    if (res.ok) {
      let data = await res.json();
      console.log(data);
      return { data };
    }
  }
);

const dictionarySlice = createSlice({
  name: "dictionary",
  initialState: [],
  reducers: {},
  extraReducers: {
    [getDictionaryAsync.fulfilled]: (state, action) => {
      return action.payload.dictData;
    },
    [addWordtoDictAsync.fulfilled]: (state, action) => {
      console.log(action.payload.data   "reducer");
      state.push(action.payload.data);
    },
  },
});

export default dictionarySlice.reducer;
 

Ответ №1:

Вопрос

Проблема в том, что первый вызов для получения словаря изменяет инвариант состояния от массива к объекту. Объект ответа JSON от "https://vocabulary-app-be.herokuapp.com/dictionary" -это объект с message data ключами и.

 {
  "message": "Your data is here",
  "data": [ .... your dictionary data array ]
}
 

getDictionaryAsync Возвращает объект с dictData ключом.

 export const getDictionaryAsync = createAsyncThunk(
  "dictionary/getDictAsync",
  async () => {
    let res = await fetch("https://vocabulary-app-be.herokuapp.com/dictionary");
    if (res.ok) {
      let dictData = await res.json();
      return { dictData }; // <-- returned in action payload
    }
  }
);
 

И случай редуктора устанавливает состояние в это значение полезной нагрузки.

 [getDictionaryAsync.fulfilled]: (state, action) => {
  return action.payload.dictData;
},
 

Теперь ваше состояние таково:

 {
  "message": "Your data is here",
  "data": [ .... your dictionary data array ]
}
 

И его нельзя втолкнуть внутрь.

Решение

Я думаю, вам просто нужен dictData.data массив в качестве полезной нагрузки или просто data свойство прямо из возвращаемого dictData объекта.

 export const getDictionaryAsync = createAsyncThunk(
  "dictionary/getDictAsync",
  async () => {
    let res = await fetch("https://vocabulary-app-be.herokuapp.com/dictionary");
    if (res.ok) {
      let dictData = await res.json();
      return dictData.data; // <-- returned data property as payload
    }
  }
);

...

[getDictionaryAsync.fulfilled]: (state, action) => {
  return action.payload; // <-- return data payload as state
},
 

Комментарии:

1. Спасибо за вашу помощь начинающему разработчику. Отличное и понятное решение.

2. @Tharun Не волнуйся, мы все с чего-то начинали. Не забудьте озвучить полезные и/или полезные вопросы, ответы и комментарии, которые вы найдете здесь, на SO. Ура и удачи.