0
votes

I have problem with destructuring Typescript data object from my own Hook created in React.

export interface InitialState {
  pokemonListLoading: false;
  pokemonListLoadingFailed: false;
  data: [];
}

interface FetchPokemonList {
  type: typeof FETCH_POKEMON_LIST;
}

interface FetchPokemonListSuccess {
  type: typeof FETCH_POKEMON_LIST_SUCCESS;
  payload: PokemonList;
}

...

export type PokemonListActionTypes = FetchPokemonList | FetchPokemonListSuccess | FetchPokemonListError;

const dataFetchReducer = (state: InitialState, action: PokemonListActionTypes) => {
  switch (action.type) {
    case FETCH_POKEMON_LIST:
      return {
        ...state,
        pokemonListLoading: true,
        pokemonListLoadingFailed: false,
      };
    case FETCH_POKEMON_LIST_SUCCESS:
      return {
        ...state,
        pokemonListLoading: false,
        pokemonListLoadingFailed: false,
        data: action.payload,
      };
    case FETCH_POKEMON_LIST_ERROR:
      return {
        ...state,
        pokemonListLoading: false,
        pokemonListLoadingFailed: true,
      };
    default:
      throw new Error();
  }
};

export const fetchPokemonList = (initialUrl: string, initialData: []) => {
  const [url, setUrl] = useState(initialUrl);
  const [state, dispatch] = useReducer(dataFetchReducer, {
    pokemonListLoading: false,
    pokemonListLoadingFailed: false,
    data: initialData,
  });

  useEffect(() => {
    const fetchData = async () => {
      dispatch({ type: FETCH_POKEMON_LIST });
      try {
        const result = await axios(url);
        dispatch({ type: FETCH_POKEMON_LIST_SUCCESS, payload: result.data });
      } catch (error) {
        dispatch({ type: FETCH_POKEMON_LIST_ERROR });
      }
    };

    fetchData();
  }, [url]);

  return [state, setUrl];
};

and whole component

import React, { FunctionComponent } from 'react';
import { fetchPokemonList, InitialState } from '../../hooks/fetchPokemonList';

const PokemonList: FunctionComponent = () => {
  const [{
      data: { results: pokemonList },
      pokemonListLoading,
      pokemonListLoadingFailed,
    },
  ] = fetchPokemonList('https://pokeapi.co/api/v2/pokemon',[]);

  return (
    <div>
      PokemonList
      {pokemonListLoading ? (
        <div>Laoding...</div>
      ) : (
      pokemonList && pokemonList.map((pokemon: { name: string}) => (
          <div key={pokemon.name}>{pokemon.name}</div>
        ))
      )}
      {pokemonListLoadingFailed && <div>Error</div>}
    </div>
  )
}

export { PokemonList }

error code displayed by Webstorm

TS2339: Property 'data' does not exist on type '{ pokemonListLoading: boolean; pokemonListLoadingFailed: boolean; data: []; } | { pokemonListLoading: boolean; pokemonListLoadingFailed: boolean; data: PokemonList; } | Dispatch ...>>'.

1

1 Answers

0
votes

The issue is within this line:

dispatch({ type: FETCH_POKEMON_LIST_SUCCESS, payload: result.data });

Where you send as payload without using a key for your new data value.

Then in the code section you're setting data with the payload object, which results in the error you're experiencing:

case FETCH_POKEMON_LIST_SUCCESS:
  return {
    ...state,
    pokemonListLoading: false,
    pokemonListLoadingFailed: false,
    data: action.payload,
  };

Try passing your payload like this: payload: { data: result.data }.
Then set your data respectively: data: action.payload.data