无法使用 UseCallback 内部的参数访问函数
Unable to acess a Function with parameters inside of UseCallback
我有一个通过 Params 接收 ID 号的页面(屏幕),在这个屏幕中,我尝试从我的 Action(reducer)文件中调用一个 Action Function 并获得一个 API 调用,我想我没有从该调用中获得数组中的任何信息,我相信问题出在调用中,但我在 Action Function 的声明之后放置了一个控制台日志,但它没有打印,所以我认为它没有'无法访问该函数,所以我认为问题在于通过 Dispatch 调用该函数。
我什至尝试在 UseEfect 中放置一个断点,我在其中调用调用 Dispatch 函数的函数,但它永远不会中断我不确定错误在哪里,这是代码:
屏幕(我怀疑问题所在):
```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.playerGoals);
const dispatch = useDispatch();
const loadEstad = useCallback (async (param) => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(userActions.fetchEstadistica(param));
} 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
风格=StyleSheet.create({
图片: {
宽度:'100%',
身高:300,
},
副标题:{
字体大小:16,
textAlign: 'justify',
边距垂直:20,
字体粗细:'normal',
},
描述: {
字体大小:16,
textAlign: 'center',
边距垂直:20,
字体粗细:'bold',
},
dataContainer:{
width: '80%',
alignItems: 'center',
marginHorizontal: 40,
},
actions: {
marginVertical: 10,
alignItems: 'center',
},
});
export default ProductDetailScreen
;```
这是我的动作文件:
import ResultadoEstadistica from '../../models/estadistica/resultadoEstadistica';
import PlayerEstadistica from '../../models/estadistica/playerEstatisticData';
import Cards from '../../models/estadistica/cards';
import Games from '../../models/estadistica/games';
import Goals from '../../models/estadistica/goals';
export const SET_JUGADORES = 'SET_JUGADORES';
export const SET_ESTADISTICA = 'SET_ESTADISTICA';
export const fetchJugadores = () => {
return async (dispatch) => {
//any async code here!!!
try {
const response = await fetch(
'https://alianzafc2021-default-rtdb.firebaseio.com/jugadores.json'
);
if (!response.ok) {
throw new Error('Algo salio Mal!');
}
const resData = await response.json();
const loadedJugadores = [];
for (const key in resData) {
loadedJugadores.push(
new Jugador(
key,
resData[key].altura,
resData[key].apellido,
resData[key].edad,
resData[key].fecha_nacimiento,
resData[key].iso_code,
resData[key].imagen,
resData[key].lugar_nacimiento,
resData[key].nacionalidad,
resData[key].nombre_completo,
resData[key].nombre_corto,
resData[key].nombres,
resData[key].numero,
resData[key].pais,
resData[key].peso,
resData[key].player_id,
resData[key].posicion
)
);
}
dispatch({ type: SET_JUGADORES, players: loadedJugadores });
} catch (err) {
throw err;
}
};
}
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: {
'x-rapidapi-key': Here goes my API KEY,
'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('***Impresion desde la accion***');
console.log(resData);
console.log('***Fin de Impresionc***');
//Arrays de la Estadistica del Jugador
const loadedEstadistica = [];
const loadedCards = [];
const loadedGoals = [];
const loadedGames = [];
for (const key in resData) {
loadesApiResult.push(
new ResultadoEstadistica(
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: loadesApiResult, goles: loadedGoals, juegos: loadedGames, tarjetas: loadedCards });
} catch (err) {
throw err;
}
};
};```
最后这是我的 Redux Reducer 以防万一:
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: estadistica,
playerGoals: action.goles,
playerCards: action.tarjetas,
playerGames: action.juegos
};
}
return state;
};
抱歉格式问题,但给我带来了一些问题;有什么想法是我的问题吗?
谢谢。
您的 screen
代码存在一些问题,因此我建议在添加任何其他内容之前简化逻辑以确保其正常工作。
替换为:
const loadEstad = useCallback (async (param) => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(userActions.fetchEstadistica(param));
} 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);
有了这个:
useEffect(()=>{
if (estadId) dispatch(userActions.fetchEstadistica(estadId));
},[estadId]);
假设您的 reducer/action 代码是正确的,那么每次参数 estadId
更改时都应该调用 api。 loading/refresh 应该在减速器中而不是在 screen
组件上设置。
需要牢记的几点:
不要等待发货。
console.log 在 promise 解析代码块之外的状态变量将不起作用。
下面这个不行。相反,您应该将加载变量设置为在 API 返回数据后更新的 redux 变量。
loadEstad(estadId).then(() => {
setIsLoading(假);
});
我有一个通过 Params 接收 ID 号的页面(屏幕),在这个屏幕中,我尝试从我的 Action(reducer)文件中调用一个 Action Function 并获得一个 API 调用,我想我没有从该调用中获得数组中的任何信息,我相信问题出在调用中,但我在 Action Function 的声明之后放置了一个控制台日志,但它没有打印,所以我认为它没有'无法访问该函数,所以我认为问题在于通过 Dispatch 调用该函数。
我什至尝试在 UseEfect 中放置一个断点,我在其中调用调用 Dispatch 函数的函数,但它永远不会中断我不确定错误在哪里,这是代码:
屏幕(我怀疑问题所在):
```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.playerGoals); const dispatch = useDispatch(); const loadEstad = useCallback (async (param) => { setError(null); setIsRefreshing(true); try { await dispatch(userActions.fetchEstadistica(param)); } 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
风格=StyleSheet.create({ 图片: { 宽度:'100%', 身高:300, }, 副标题:{ 字体大小:16, textAlign: 'justify', 边距垂直:20, 字体粗细:'normal', }, 描述: { 字体大小:16, textAlign: 'center', 边距垂直:20, 字体粗细:'bold',
}, dataContainer:{ width: '80%', alignItems: 'center', marginHorizontal: 40, }, actions: { marginVertical: 10, alignItems: 'center', }, }); export default ProductDetailScreen ;```
这是我的动作文件:
import ResultadoEstadistica from '../../models/estadistica/resultadoEstadistica'; import PlayerEstadistica from '../../models/estadistica/playerEstatisticData'; import Cards from '../../models/estadistica/cards'; import Games from '../../models/estadistica/games'; import Goals from '../../models/estadistica/goals'; export const SET_JUGADORES = 'SET_JUGADORES'; export const SET_ESTADISTICA = 'SET_ESTADISTICA'; export const fetchJugadores = () => { return async (dispatch) => { //any async code here!!! try { const response = await fetch( 'https://alianzafc2021-default-rtdb.firebaseio.com/jugadores.json' ); if (!response.ok) { throw new Error('Algo salio Mal!'); } const resData = await response.json(); const loadedJugadores = []; for (const key in resData) { loadedJugadores.push( new Jugador( key, resData[key].altura, resData[key].apellido, resData[key].edad, resData[key].fecha_nacimiento, resData[key].iso_code, resData[key].imagen, resData[key].lugar_nacimiento, resData[key].nacionalidad, resData[key].nombre_completo, resData[key].nombre_corto, resData[key].nombres, resData[key].numero, resData[key].pais, resData[key].peso, resData[key].player_id, resData[key].posicion ) ); } dispatch({ type: SET_JUGADORES, players: loadedJugadores }); } catch (err) { throw err; } }; } 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: { 'x-rapidapi-key': Here goes my API KEY, '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('***Impresion desde la accion***'); console.log(resData); console.log('***Fin de Impresionc***'); //Arrays de la Estadistica del Jugador const loadedEstadistica = []; const loadedCards = []; const loadedGoals = []; const loadedGames = []; for (const key in resData) { loadesApiResult.push( new ResultadoEstadistica( 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: loadesApiResult, goles: loadedGoals, juegos: loadedGames, tarjetas: loadedCards }); } catch (err) { throw err; } }; };```
最后这是我的 Redux Reducer 以防万一:
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: estadistica,
playerGoals: action.goles,
playerCards: action.tarjetas,
playerGames: action.juegos
};
}
return state;
};
抱歉格式问题,但给我带来了一些问题;有什么想法是我的问题吗?
谢谢。
您的 screen
代码存在一些问题,因此我建议在添加任何其他内容之前简化逻辑以确保其正常工作。
替换为:
const loadEstad = useCallback (async (param) => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(userActions.fetchEstadistica(param));
} 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);
有了这个:
useEffect(()=>{
if (estadId) dispatch(userActions.fetchEstadistica(estadId));
},[estadId]);
假设您的 reducer/action 代码是正确的,那么每次参数 estadId
更改时都应该调用 api。 loading/refresh 应该在减速器中而不是在 screen
组件上设置。
需要牢记的几点:
不要等待发货。
console.log 在 promise 解析代码块之外的状态变量将不起作用。
下面这个不行。相反,您应该将加载变量设置为在 API 返回数据后更新的 redux 变量。
loadEstad(estadId).then(() => { setIsLoading(假); });