skip to Main Content

My Redux project uses Redux-Thunk to work with an API, it doesn’t render the Header.js element as it was supposed to, I’ll show you the files (they are VERY short). I won’t waste time showing the store and App.js because I’m sure it is correctly configured. (but if you want I’ll share)

Redux > actions:

export const FETCH_CHARACTERS_BEGIN = 'FETCH_CHARACTERS_BEGIN';

export const FETCH_CHARACTERS_SUCCESS = 'FETCH_CHARACTERS_SUCCESS';

export const FETCH_CHARACTERS_FAILURE = 'FETCH_CHARACTERS_FAILURE';

export const actionFetchCharactersBegin = () => ({
    type: FETCH_CHARACTERS_BEGIN,
});

export const actionFetchCharactersSucess = (characters) => ({
    type: FETCH_CHARACTERS_SUCCESS,
    payload: characters,
});

export const actionFetchCharactersFailure = (error) => ({
    type: FETCH_CHARACTERS_FAILURE,
    payload: error,
});

const API = 'https://rickandmortyapi.com/api/character';

export function fetchCharacters() {
    return async (dispatch) => {
        dispatch(actionFetchCharactersBegin());
        try {
            const response = await fetch(API);
            const { results } = await response.json();
            dispatch(actionFetchCharactersSucess(results));
            return results;
        } catch (error) {
            dispatch(actionFetchCharactersFailure(error));
        }
    };
};

redux > reducers:

import {
    FETCH_CHARACTERS_BEGIN,
    FETCH_CHARACTERS_SUCCESS,
    FETCH_CHARACTERS_FAILURE
} from '../actions';

const initialState = {
    characters: [],
    loading: false,
    error: null
}

export default function characterReducer(state = initialState, action) {
    switch (action.type) {
        case FETCH_CHARACTERS_BEGIN:
            return {
                ...state,
                loading: true,
                error: null
            };
        case FETCH_CHARACTERS_SUCCESS:
            return {
                ...state,
                loading: false,
                characters: [...state.characters, action.payload]
            };
        case FETCH_CHARACTERS_FAILURE:
            return {
                ...state,
                loading: false,
                error: action.payload,
                characters: []
            }
        default:
            return state;
    }
};

components > Header.js:

import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchCharacters } from '../redux/actions';
import './Header.css'

function Header() {

    const characters = useSelector(state => state.characters);
    const loading = useSelector(state => state.loading);
    const error = useSelector(state => state.error);
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(fetchCharacters())
    }, [dispatch]);

    if (loading) {
        return <div>Loading...</div>
    };

    if (error) {
        return <div>{error.message}</div>
    };

    return (
        <div className='container-header'>
            <div className='header'>
                <div className='header_logo'>
                    <div className='logo_text'>
                        <h3>Rick And Morty Character's</h3>
                    </div>
                </div>
                <h1>Characters</h1>
                <ul>
                    {characters.map(character => ( 
                        <li key={character.id}>
                            {character.name} ({character.status})
                        </li>    
                    ))}
                </ul>
            </div>
        </div>
    )
}

export default Header;

can someone help me to find out the problem?

2

Answers


  1. Chosen as BEST ANSWER

    strange, it still doesn't render anything on the screen, can you check what's wrong in the repository for me? I'll send the link:

    https://github.com/eliasef/rick-and-morty-api


  2. Issue

    The only issue/discrepancy I see in the code is in the characterReducer reducer function in the FETCH_CHARACTERS_SUCCESS success case. The fetchCharacters action returns an array of characters, but the FETCH_CHARACTERS_SUCCESS case incorrectly nests this result array in the state.characters array.

    In other words, each time FETCH_CHARACTERS_SUCCESS runs it nests an array in an array.

    export function fetchCharacters() {
      return async (dispatch) => {
        dispatch(actionFetchCharactersBegin());
        try {
          const response = await fetch(API);
          const { results } = await response.json();
          dispatch(actionFetchCharactersSucess(results));
          return results;
        } catch (error) {
          dispatch(actionFetchCharactersFailure(error));
        }
      };
    };
    

    enter image description here

    case FETCH_CHARACTERS_SUCCESS:
      return {
        ...state,
        loading: false,
        characters: [
          ...state.characters,
          action.payload // [{ id: 1, name: "Rick Sanchez", …}, ...]
        ]
      };
    

    The result is that state.characters looks something like [[{ id: 1, name: "Rick Sanchez", …}, ...]].

    Solution

    You can either save the payload array directly:

    case FETCH_CHARACTERS_SUCCESS:
      return {
        ...state,
        loading: false,
        characters: action.payload,
      };
    

    Or if you are actually using the paginated results you can spread the payload:

    case FETCH_CHARACTERS_SUCCESS:
      return {
        ...state,
        loading: false,
        characters: [
          ...state.characters,
          ...action.payload
        ]
      };
    

    Edit my-redux-project-doesnt-render-and-i-dont-know-where-the-error-is

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search