reactjs - React-typescript-Redux-toolkit: misslyckades med att hämta inbäddad api


Jag övar på redux-toolkit med typescript. Jag har använt en öppen API och för att hämta data använde jag redux toolkits createAsyncThunk. Jag lyckades hämta datan i appens komponent. När jag loggar det i konsolen kan jag se datan, men så fort jag mappar data.result får jag fel: TypeError: Cannot read property 'map' of undefined. Jag tror att jag har gjort ett Typescript-fel när jag använde gränssnittet. Men jag ser inte var problemet är och även i Chromes reduxdevtools: data förväntar sig ett objekt men jag satte arrayer. Så här ser min redux-devtools ut. Jag delade min kod i Codesand Box.

PS: I am sharing only these two files below because I think this is where I making mistakes

Detta är min Reducer, jag tror att jag gör ett misstag med typerna

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

export const dataFetch = createAsyncThunk(
  `store/dataFetch`,
  async () => {
    const url = `https://rickandmortyapi.com/api/character`;
    const response = await fetch(url);
    const data = await response.json();
    return data;
  }
);

interface Meta {
  loading: boolean;
  error: boolean;
  message: string;
}
// This is where I am making mistake
interface Results {
  name: string;
  image: string;
  gender: string;
  species: string;
  status: string;
}

interface Info {
  count: number;
  pages: number;
}

interface User {
  results: Results[];
  info: Info;

}

export interface IUser {
  meta: Meta;
  data: User[];
}

const initialState: IUser = {
  "meta": {
    "loading": false,
    "error": false,
    "message": ``
  },
  "data": []
};

const UserSlice = createSlice({
  "name": `JsonPlacehoder user`,
  initialState,
  "reducers": {

  },
  "extraReducers": (builder) => {
    builder.addCase(dataFetch.pending, (state) => (
      {
        ...state,
        "meta": {
          ...state.meta,
          "loading": true
        }
      }
    ));
    builder.addCase(dataFetch.fulfilled, (state, { payload }) => (
      {
        ...state,
        "meta": {
          ...state.meta,
          "loading": false,
          "error": false,
          "message": ``
        },
        "data": payload
      }
    ));
    builder.addCase(dataFetch.rejected, (state, { error }) => {
      window.alert(error?.message);
      return {
        ...state,
        "meta": {
          "loading": false,
          "error": true,
          "message": error?.message || ``
        }
      };
    });
  }
});

export default UserSlice.reducer;

Detta är min komponent där jag får fel när jag använder map-funktionen

import React, { useEffect } from 'react';

import { useSelector, useDispatch } from 'react-redux'

import { dataFetch } from './store/reducers';
import { IRootState } from './store/combineReducers';

function App() {

  const { data, meta } = useSelector((rootState: IRootState) => rootState.fetchUser);

  console.log(data);

  const dispatch = useDispatch()


  useEffect(() => {
    dispatch(dataFetch())
  }, [dispatch])

  return (
    <div className="App">
      {
        data.results.map(i => { //GETTING ERROR
          return <div>
            <h1>{i.name}</h1>
          </div>
        })
      }
    </div>
  );
}

export default App;

Svar #1

Det beror på att du försöker .map över datan innan hämtningen ens har börjat.

Din useEffect triggas efter den första renderingen. Innan dess har du redan försökt att .map en gång. Och ändå, under laddning, kan din komponent renderas om.

Det tillsammans med att vissa av dina reducerare faktiskt tenderar att ta bort attributet data i stället för att behålla data: [] (jag tittar på pending där) leder till att data blir odefinierat vid vissa renderingar.

Ett TypeError är faktiskt inte ett TypeScript-fel (dessa börjar alltid med "ts" följt av ett nummer), utan ett JavaScript-runtime-fel. Så du har verkligen en "runtime-krasch" här.