Incapaz de obtener información sobre un Reductor usando Redux

Tengo una pregunta con un Reductor, el problema es que estoy acostumbrada a obtener datos de una API que trae sólo el valor clave Parejas algo como:

       {
        "-MObNVR5e180MfhvtbRY": {
            "altura": "179 cm",
            "apellido": "Cuéllar De León",
            "edad": 31,
            "fecha_nacimiento": "20/10/1989",
            "imagen": "https://firebasestorage.googleapis.com/v0/b/alianzafc2021.appspot.com/o/yimmi%20cuellar.jpg?alt=media&token=144fa106-eabb-40c8-83b6-2e4b45034eda",
            "iso_code": "SV",
            "lugar_nacimiento": "San Julián",
            "nacionalidad": "El Salvador",
            "nombre_completo": "Yimmy Rodrigo Cuéllar De León",
            "nombre_corto": "Yimmy Cuéllar",
            "nombres": "Yimmy Rodrigo",
            "numero": 1,
            "pais": "El Salvador",
            "peso": "66 kg",
            "player_id": 108911,
            "posicion": "Portero"
        },
    }

Ahora necesito obtener los datos de una API que tiene Arrays dentro del Array así:

{
    "api": {
        "results": 13,
        "players": [
            {
                "player_id": 79308,
                "player_name": "Felipe Ponce Ramírez",
                "firstname": "Felipe",
                "lastname": "Ponce Ramírez",
                "number": null,
                "position": "Midfielder",
                "age": 32,
                "birth_date": "29/03/1988",
                "birth_place": "Ciudad Lerdo",
                "birth_country": "Mexico",
                "nationality": "Mexico",
                "height": "177 cm",
                "weight": "67 kg",
                "injured": null,
                "rating": null,
                "team_id": 4299,
                "team_name": "Alianza",
                "league_id": 2979,
                "league": "Primera Division",
                "season": "2020-2021",
                "captain": 0,
                "shots": {
                    "total": 0,
                    "on": 0
                },
                "goals": {
                    "total": 4,
                    "conceded": 0,
                    "assists": 0,
                    "saves": 0
                },
                "passes": {
                    "total": 0,
                    "key": 0,
                    "accuracy": 0
                },
                "tackles": {
                    "total": 0,
                    "blocks": 0,
                    "interceptions": 0
                },
                "duels": {
                    "total": 0,
                    "won": 0
                },
                "dribbles": {
                    "attempts": 0,
                    "success": 0
                },
                "fouls": {
                    "drawn": 0,
                    "committed": 0
                },
                "cards": {
                    "yellow": 2,
                    "yellowred": 0,
                    "red": 0
                },
                "penalty": {
                    "won": 0,
                    "commited": 0,
                    "success": 0,
                    "missed": 0,
                    "saved": 0
                },
                "games": {
                    "appearences": 6,
                    "minutes_played": 194,
                    "lineups": 2
                },
                "substitutes": {
                    "in": 4,
                    "out": 2,
                    "bench": 0
                }
            },
}

Alguien me dijo que necesitaré crear un Modelo de Datos para cada SubArray así que lo hice y lo usé en mi Archivo de Acción así:

export const fetchEstadistica = player_id => {
    return async (dispatch) => {
        //any async code here!!!
        try {
            const response = await fetch(
                `https://api-football-v1.p.rapidapi.com/v2/players/player/${player_id}.json`,
                {
                    method: 'GET',
                    headers: new Headers({
                        'x-rapidapi-key': //Here Goes My API Key which I keep for Security Reasons,
                        'x-rapidapi-host': 'api-football-v1.p.rapidapi.com',
                        'useQueryString': 'true'
                    })
                }
            );

            if (!response.ok) {
                throw new Error('Algo salio Mal!');
            }

            const resData = await response.json();
            const loadesApiResult = [];

            console.log(resData);

            //Arrays de la Estadistica del Jugador
            const loadedEstadistica = [];
            const loadedCards = [];
            const loadedGoals = [];
            const loadedGames = [];

            for (const key in resData) {
                loadesApiResult.push(
                    new ResultadoEstadistica(
                        key,
                        resData[key].results,
                        resData[key].players
                    )
                );
            }

            const apiData = loadesApiResult.players;

            for (const key in apiData){
                loadedEstadistica.push(
                    new PlayerEstadistica (
                        apiData[key].player_id,
                        apiData[key].player_name,
                        apiData[key].firstname,
                        apiData[key].lastname,
                        apiData[key].number,
                        apiData[key].position,
                        apiData[key].age,
                        apiData[key].birth_date,
                        apiData[key].birth_place,
                        apiData[key].birth_country,
                        apiData[key].nationality,
                        apiData[key].height,
                        apiData[key].weight,
                        apiData[key].injured,
                        apiData[key].rating,
                        apiData[key].team_id,
                        apiData[key].team_name,
                        apiData[key].league_id,
                        apiData[key].league,
                        apiData[key].season,
                        apiData[key].captain,
                        apiData[key].shots,
                        apiData[key].goals,
                        apiData[key].passes,
                        apiData[key].duels,
                        apiData[key].dribbles,
                        apiData[key].fouls,
                        apiData[key].cards,
                        apiData[key].penalty,
                        apiData[key].games,
                        apiData[key].substitutes,
                    )
                );
            }

            const playerDataGames = loadedEstadistica.games;
            
            for (const key in playerDataGames){
                loadedGames.push(
                    new Games(
                        playerDataGames[key].apperences,
                        playerDataGames[key].minutes_played,
                        playerDataGames[key].lineups
                    )
                );
            };

            const playerDataGoals = loadedEstadistica.goals;

            for (const key in playerDataGoals){
                loadedGoals.push(
                    new Goals(
                        playerDataGoals[key].total,
                        playerDataGoals[key].conceded,
                        playerDataGoals[key].assists,
                        playerDataGoals[key].saves
                    )
                );
            };

            const playerDataCards = loadedEstadistica.cards;

            for (const key in playerDataCards){
                loadedCards.push(
                    new Cards(
                        playerDataCards[key].yellow,
                        playerDataCards[key].yellowred,
                        playerDataCards[key].red
                    )
                );
            };

            dispatch({ type: SET_ESTADISTICA, estadistica: loadedEstadistica, goles: loadedGoals, juegos: loadedGames, tarjetas: loadedCards });
        } catch (err) {
            throw err;
        }
    };
};

Luego meto esto en mi lector con el Tipo:

import { SET_JUGADORES, SET_ESTADISTICA } from "../actions/jugadores";

const initialState = {
    availablePlayers: [],
    estadistica: [],
    playerGoals: [],
    playerCards: [],
    playerGames: [],
}

export default (state = initialState, action) => {
    switch (action.type) {
        case SET_JUGADORES:
            return {
                availablePlayers: action.players,
            };
        case SET_ESTADISTICA:
            return{
                estadistica: estadistica,
                // playerGoals: action.goles,
                // playerCards: action.tarjetas,
                // playerGames: action.juegos
            };
    }
    return state;
};

Finalmente, voy a llamar al Reductor de:

import React, {useState, useCallback, useEffect} from 'react';
import { ScrollView, Text, Image, StyleSheet, View } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';

const ProductDetailScreen = props => {
    const playerId = props.route.params.id;
    const estadId = props.route.params.statId;

    const selectedPlayer = useSelector(state => state.jugadores.availablePlayers.find(prod => prod.id === playerId));


    const [isLoading, setIsLoading] = useState(false);
    const [isRefreshing, setIsRefreshing] = useState(false);
    const [error, setError] = useState();

    const goles = useSelector(state => state.jugadores.estadistica);

    const dispatch = useDispatch();

    const loadEstad = useCallback (async (estadId) => {
        setError(null);
        setIsRefreshing(true);
        try {
            await dispatch(userActions.fetchEstadistica(estadId));
        } catch (err){
            setError(err.message);
        }
        setIsRefreshing(false);
    }, [dispatch, setIsLoading, setError]);

    useEffect(() => {       
        setIsLoading(true); 
        loadEstad(estadId).then(() => {
            setIsLoading(false);
        });
    }, [dispatch, loadEstad]);

    console.log(estadId);
    console.log(goles);

    return (
        
            
            
                Numero: {selectedPlayer.numero}
                Nombre Completo: {selectedPlayer.nombre_completo}
                Posicion: {selectedPlayer.posicion} 
                Edad: {selectedPlayer.edad}
                Nacionalidad: {selectedPlayer.nacionalidad}
            
        
    );
};

export const screenOptions = navData => {
    return {
        headerTitle: navData.route.params.nombre,
    }
};

const styles = StyleSheet.create({
    image: {
        width: '100%',
        height: 300,
    },
    subtitle: {
        fontSize: 16,
        textAlign: 'justify',
        marginVertical: 20,
        fontWeight:'normal',
    },
    description: {
        fontSize: 16,
        textAlign: 'center',
        marginVertical: 20,
        fontWeight: 'bold',

    },
    dataContainer:{
        width: '80%',
        alignItems: 'center',
        marginHorizontal: 40,
    },
    actions: {
        marginVertical: 10,
        alignItems: 'center',
    },
});

export default ProductDetailScreen;

Sin embargo, cuando voy a ver la Terminal veo que cuando hago la consola.log (goles) que recibe la rebanada del Reductor me desfigura.

No estoy seguro de lo que estoy haciendo mal, ¿alguna idea?

Regards Kind

Pregunta hecha hace 3 años, 4 meses, 27 días - Por techinnovator


3 Respuestas:

  • Prueba esto.

    import { SET_JUGADORES, SET_ESTADISTICA } from "../actions/jugadores";
    
    const initialState = {
        availablePlayers: [],
        estadistica: [],
        playerGoals: [],
        playerCards: [],
        playerGames: [],
    }
    
    export default (state = initialState, action) => {
        switch (action.type) {
            case SET_JUGADORES:
                return {
                    ...state,
                    availablePlayers: action.players,
                };
            case SET_ESTADISTICA:
                return{
                    ...state,
                    estadistica: state.estadistica,
                    // playerGoals: action.goles,
                    // playerCards: action.tarjetas,
                    // playerGames: action.juegos
                };
        }
        return state;
    };
    

    Respondida el Dec 18, 2020 a las 14:42 - por pixelpioneerbbb5

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás enfrentando se debe a que en tu Reductor estás tratando de acceder a las propiedades de la acción sin hacer referencia adecuada al objeto action en cada caso. En la parte donde manejas el caso SET_ESTADISTICA, estás tratando de acceder a las propiedades de la acción directamente, pero deberías hacerlo a través del objeto action.

    Aquí te muestro cómo puedes corregirlo en tu Reductor:

    javascript
    import { SET_JUGADORES, SET_ESTADISTICA } from "../actions/jugadores";
    
    const initialState = {
        availablePlayers: [],
        estadistica: [],
        playerGoals: [],
        playerCards: [],
        playerGames: [],
    }
    
    export default (state = initialState, action) => {
        switch (action.type) {
            case SET_JUGADORES:
                return {
                    availablePlayers: action.players,
                };
            case SET_ESTADISTICA:
                return {
                    estadistica: action.estadistica,
                    playerGoals: action.goles,
                    playerCards: action.tarjetas,
                    playerGames: action.juegos
                };
            default:
                return state;
        }
    };
    

    Recuerda que debes usar action.estadistica, action.goles, action.tarjetas y action.juegos en lugar de solo estadistica, goles, tarjetas y juegos en tu Reductor.

    Además, asegúrate de que el nombre de las propiedades que estás intentando acceder en el Reductor coincida con las propiedades de la acción que estás enviando desde tu Acción.

    Espero que esta corrección te ayude a solucionar el problema que estás experimentando. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 19, 2020 a las 14:41 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Hay un par de problemas potenciales en tu código:

    Tipo de datos incorrecto en el estado Redux:

    En el selector const goles = useSelector(state => state.jugadores.estadistica);, estás guardando todos los datos de estadistica en la variable goles, lo cual no es correcto. estadistica contiene un array de objetos PlayerEstadistica, pero goles debería contener un array de objetos Goals.

    Acceso a datos anidados en el selector:

    En el selector const goles = useSelector(state => state.jugadores.estadistica);, estás accediendo a estadistica directamente. Sin embargo, en tu acción SET_ESTADISTICA, estás asignando estadistica al objeto de estado, en lugar de a un campo específico. Esto significa que no puedes acceder a estadistica directamente en el selector.

    Solución:

    Para resolver estos problemas, debes actualizar tu reductor y selector de la siguiente manera:

    Reducer:

    
    export default (state = initialState, action) => {
        switch (action.type) {
            case SET_JUGADORES:
                return {
                    availablePlayers: action.players,
                };
            case SET_ESTADISTICA:
                return {
                    ...state,
                    estadistica: action.estadistica,
                    playerGoals: action.goles,
                    playerCards: action.tarjetas,
                    playerGames: action.juegos
                };
        }
        return state;
    };
    

    Selector:

    
    const goles = useSelector(state => state.jugadores.playerGoals);
    

    Estos cambios asegurarán que los datos de goles se almacenen en el campo correcto del estado Redux y que se puedan acceder correctamente en el selector.

    Respondida el Dec 19, 2020 a las 14:51 - por Gemini

    Votos positivos: 0 | Votos negativos: 0