Home > Net >  How do I access the props of an object after mapping through in React w/ Redux?
How do I access the props of an object after mapping through in React w/ Redux?

Time:09-17

I'm new to React and Redux, and I'm trying to make an app based on a public Animal Crossing API. I was having issues initially because after I got the data from the API and tried to map in the component, it said it was an object. I read a lot of different things on StackOverflow. I tried using Object.entries on the initial API response, that helped somewhat. I was able to make a card component for each villager. But I can't access the props in the data itself to have the names, personalities, and birthdays show up. I've been trying to do my first API call for about 3 weeks and tried several different projects and tutorials but I end up hitting a wall since I'm a beginner and still pretty confused.

Can someone try looking at my code to see where I'm going wrong?

This is my actions & initial API call:

import { FETCH_CHARACTERS_REQUEST, FETCH_CHARACTERS_SUCCESS, FETCH_CHARACTERS_FAILURE } from "./actiontypes";
import axios from 'axios';

export const fetchCharactersRequest = () => {
    return {
        type: FETCH_CHARACTERS_REQUEST
    }
}

const fetchCharactersSuccess = characters => {
    return {
        type: FETCH_CHARACTERS_SUCCESS,
        payload: characters
    }
}

const fetchCharactersFailure = error => {
    return {
        type: FETCH_CHARACTERS_FAILURE,
        payload: error
    }
}

export const fetchCharacters = () => {
    return (dispatch) => {
        dispatch(fetchCharactersRequest)
         axios.get('https://acnhapi.com/v1/villagers')
        .then(response => {
            const characters = Object.entries(response.data)
            dispatch(fetchCharactersSuccess(characters))
        })
        .catch(error => {
            const errorMsg = error.message
            dispatch(fetchCharactersFailure(errorMsg))
        })
    }
}

This is my reducer & initial state:

import {
    FETCH_CHARACTERS_REQUEST,
    FETCH_CHARACTERS_SUCCESS,
    FETCH_CHARACTERS_FAILURE
} from './actiontypes';

const initialState = {
    characters: [],
    isLoading: false,
    error: ''
}

const reducer = (state = initialState, action) => {
    switch(action.type) {
        case FETCH_CHARACTERS_REQUEST:
            return {
                ...state,
                isLoading: true
            }
        case FETCH_CHARACTERS_SUCCESS:
            return {
                ...state,
                characters: action.payload,
                error: ''
            }
        case FETCH_CHARACTERS_FAILURE:
            return {
                loading: false,
                characters: [],
                error: action.payload
            }
        default: return state
    }
}

export default reducer;

This is where I'm having a lot of issues with my mapping. I was able to successfully console.log(characterData.characters[0][1].personality) for the first villager, but I don't know how to get that right on the map.

import React, {useEffect} from 'react';
import {connect} from 'react-redux';
import {fetchCharacters} from '../features/characterActions';
import CharacterCard from './CharacterCard';



function CharacterProfile({fetchCharacters, characterData})  {



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


    const listVillagers = characterData.characters.map((villager) =>
    <CharacterCard key={villager.key} data={villager} />
    )
  
    console.log(listVillagers)

    return characterData.isLoading ? (
        <h2>Loading...</h2>
    ) : characterData.error ? (
        <h2>{characterData.error}</h2>
    ) : (
        <div>
            <h2>Animal Crossing Villagers</h2>
            <div>
                {listVillagers}
            </div>
    
    </div>
    
    )}


const mapStateToProps = state => {
    return {
        characterData: state.character
    }
}

const mapDispatchToProps = dispatch => {
    return {
        fetchCharacters: () => dispatch(fetchCharacters())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(CharacterProfile)

And this is the character card where I was attempting to get the information from the data.

import React from 'react'

function CharacterCard({name, birthday}) {

    return (
        <div>
           <h2>Name: {name}</h2>
          
        </div>
    )
}

export default CharacterCard

Also, this is where I'm pulling the data from if it helps: https://acnhapi.com/v1/villagers

I feel like these are the main places that I could have gone wrong. I really need help because it's starting to drive me insane.

CodePudding user response:

  1. In CharacterProfile component, you can try to console your "villager"

    const listVillagers = characterData.characters.map((villager) =>
       console.log(villager)
    )
    

    it would be an array with 2 elements, like this:

    ["ant00", {"id": 1,"file-name": "ant00","name": {...}, "personality": "Cranky", ...]
    

    so if you only need second element in villager, you shold pass it like this:

    const listVillagers = characterData.characters.map((villager) =>
        <CharacterCard key={villager.key} data={villager[1]} />
    )
    
  2. because you pass villager[1] as "data" prop to CharacterCard, so in this component, you should destrucure props to "data" prop

    function CharacterCard({ data }) {
     ...
    }
    
  3. and your "data" is a object includese properties "name", "birthday", ..., so if you want to access them, you also need to destructure from "data"

    const { name, birthday } = data;
    
  4. your name is a object, too.

    "name": {
          "name-USen": "Cyrano",
          "name-EUen": "Cyrano",
          ...
    }
    

    so you cannot render it in div directly, if you want to render "name-USen", you should use name["name-USen"]

    <h2>Name: {name["name-USen"]}</h2>
    

Here is the complete code:

import React from "react";

function CharacterCard({ data }) {
  const { name, birthday } = data;

  return (
    <div>
      <h2>Name: {name["name-USen"]}</h2>
      <h2>Birthday: {birthday}</h2>
    </div>
  );
}

export default CharacterCard;
  • Related