我尝试在点击 onPress 时使用我的自定义挂钩,它会收到一个参数,但在调用它后会返回无效的挂钩调用。我想通过调用一个函数来调用我更新的自定义挂钩,该函数会将参数(我的意思是参数)传递给我的自定义挂钩,以便它加载所选的网址。
我的代码:
const PokemonListItem: React.FC<PokemonItemProps> = ({dataPokemon}) => {
const [pokemon, setPokemon] = useState<IPokemonAttributes>();
const [modalVisible, setModalVisible] = useState(false);
const pokemonsData = (chosenPokemonUrl: string) => {
const {data, isLoading} = usePokemonAttributes(chosenPokemonUrl);
setPokemon(data);
setModalVisible(true);
console.log(data);
};
return (
<View>
//this DOESNT work
<TouchableOpacity onPress={() => pokemonsData(dataPokemon.url)}>
<Text style={styles.pokemonListItem}>{dataPokemon.name}</Text>
</TouchableOpacity>
</View>
);
};
我的定制挂钩:
const usePokemonAttributes = (pokemonUrl: string): IusePokemonAttributes => {
const [isLoading, setLoading] = useState(false);
//const [shouldRun, setShouldRun] = useState(true);
const [data, setData] = useState<IPokemonAttributes>();
const [error, setError] = useState('');
const abortController = new AbortController();
// const handleTap = () => {
// setShouldRun(!shouldRun);
// };
const fetchingPokemonAttributes = async () => {
setLoading(true);
try {
const response = await fetch(`${urls.baseUrl + pokemonUrl}`, {
signal: abortController.signal,
});
const json = await response.json();
setData(await json);
} catch (error) {
setError(error.message);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchingPokemonAttributes();
return () => {
abortController.abort();
};
}, [pokemonUrl]);
return {data, error, isLoading};
};
它不起作用,因为您的自定义挂钩不在
PokemonListItem
组件的主体中。在当前的实现中,从 fetchingPokemonAttributes
组件调用 PokemonListItem
有点棘手。
不要调用另一个函数来调用
fetchingPokemonAttributes
,而是直接使用 onPress
操作来调用它。
为了实现这一点,我们需要从自定义钩子中导出
fetchingPokemonAttributes
以便在 PokemonListItem
中使用它:
首先,在自定义钩子中:
const usePokemonAttributes = () => {
const [isLoading, setLoading] = useState(false);
const [data, setData] = useState<IPokemonAttributes>();
const [error, setError] = useState('');
const abortController = new AbortController();
const fetchingPokemonAttributes = async (pokemonUrl) => {
setLoading(true);
try {
const response = await fetch(`${urls.baseUrl + pokemonUrl}`, {
signal: abortController.signal,
});
const json = await response.json();
setData(json); // -----> also remove the await from here !!
} catch (error) {
setError(error.message);
} finally {
setLoading(false);
}
};
useEffect(() => {
return () => {
abortController.abort();
};
}, [pokemonUrl]);
return {data, error, isLoading, fetchingPokemonAttributes};
};
注意:由于
fetchingPokemonAttributes
需要url
,我从自定义钩子中删除了pokemonUrl
并直接使用fetchingPokemonAttributes
函数传递它。
注意:您在
await
方法中添加了 setData
关键字。这是多余的。
其次,在
PokemonListItem
中,我们需要使用 fetchingPokemonAttributes
操作来调用 onPress
。 (别忘了在这里传递网址)
const PokemonListItem: React.FC<PokemonItemProps> = ({dataPokemon}) => {
const [pokemon, setPokemon] = useState<IPokemonAttributes>();
const [modalVisible, setModalVisible] = useState(false);
const {data, error, isLoading, fetchingPokemonAttributes} = usePokemonAttributes();
useEffect(() => {
if(data.length > 0 && !error) {
setPokemon(data);
setModalVisible(true);
}
}, [data, error])
return (
<View>
<TouchableOpacity onPress={() => fetchingPokemonAttributes(dataPokemon.url)}>
<Text style={styles.pokemonListItem}>{dataPokemon.name}</Text>
</TouchableOpacity>
</View>
)
}
现在,通过
onPress
操作,将调用 fetchingPokemonAttributes
,并且自定义挂钩将返回 data
、error
、isLoading
。现在是时候在带有 PokemonListItem
钩子的 useEffect
中使用它们了。
如您所见,我在更新
pokemon
之前使用了一些规则来检查条件,您可以根据您的要求和data
类型在此处定义自定义条件。
你不能打电话
const {data, isLoading} = usePokemonAttributes(chosenPokemonUrl);
在 pokemonsData const 中,你必须在 PokemonListItem 中调用它