【发布时间】:2020-12-18 14:33:03
【问题描述】:
我有一个关于 Reducer 的问题,问题是我习惯于从 API 获取数据,该 API 只带来如下键值对:
{
"-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"
},
}
现在我需要从数组中包含数组的 API 获取数据,如下所示:
{
"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
}
},
}
有人告诉我,我需要为每个子数组创建一个数据模型,所以我这样做了,并在我的操作文件中使用它,如下所示:
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;
}
};
};
然后我将其输入到我的 Readucer 中:
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;
};
最后,我去调用 Reducer:
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 (
<ScrollView>
<Image style={styles.image} source={{ uri: selectedPlayer.imagen }} />
<View style={styles.dataContainer}>
<Text style={styles.description}>Numero: <Text style={styles.subtitle}>{selectedPlayer.numero}</Text></Text>
<Text style={styles.description}>Nombre Completo: <Text style={styles.subtitle}>{selectedPlayer.nombre_completo}</Text></Text>
<Text style={styles.description}>Posicion: <Text style={styles.subtitle}>{selectedPlayer.posicion}</Text> </Text>
<Text style={styles.description}>Edad: <Text style={styles.subtitle}>{selectedPlayer.edad}</Text></Text>
<Text style={styles.description}>Nacionalidad: <Text style={styles.subtitle}>{selectedPlayer.nacionalidad}</Text></Text>
</View>
</ScrollView>
);
};
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;
但是,当我去观看终端时,我看到当我执行 console.log(goles) 接收 Reducer 的切片时,我得到了 Undefined。
我不确定我在做什么错,有什么想法吗?
亲切的问候
【问题讨论】:
标签: react-native redux react-redux dispatch