React Native onPress调用带参自定义Hook报Invalid Hook Call错误如何解决
错误原因
- React官方明确规定Hook只能在函数组件的顶层作用域调用,不允许在事件回调、普通函数等嵌套逻辑内调用。你在点击事件触发的
pokemonsData函数内调用usePokemonAttributes,违反了该规则,所以会抛出Invalid Hook Call错误。
修复方案
将自定义Hook移到组件顶层,新增一个状态存储选中的宝可梦URL,点击时更新这个状态触发Hook重新请求即可。
第一步:修改组件代码
const PokemonListItem: React.FC<PokemonItemProps> = ({dataPokemon}) => { const [modalVisible, setModalVisible] = useState(false); // 新增状态存储选中的宝可梦url,初始为空 const [selectedPokemonUrl, setSelectedPokemonUrl] = useState<string>(''); // Hook移到组件顶层调用,传入选中的url const {data: pokemon, isLoading} = usePokemonAttributes(selectedPokemonUrl); // 点击事件仅更新选中的url const pokemonsData = (chosenPokemonUrl: string) => { setSelectedPokemonUrl(chosenPokemonUrl); }; // 监听请求返回的数据,有数据时打开弹窗 useEffect(() => { if(pokemon) { setModalVisible(true); console.log(pokemon); } }, [pokemon]) return ( <View> <TouchableOpacity onPress={() => pokemonsData(dataPokemon.url)}> <Text style={styles.pokemonListItem}>{dataPokemon.name}</Text> </TouchableOpacity> {/* 后续可在此处添加Modal组件,用modalVisible控制显隐,用isLoading做加载态展示 */} </View> ); };
第二步:优化自定义Hook(修复请求中止异常问题)
你当前的abortController每次组件渲染都会重新创建,无法正确匹配之前的请求中止逻辑,调整到useEffect内部声明即可:
const usePokemonAttributes = (pokemonUrl: string): IusePokemonAttributes => { const [isLoading, setLoading] = useState(false); const [data, setData] = useState<IPokemonAttributes>(); const [error, setError] = useState(''); const fetchingPokemonAttributes = async (abortSignal: AbortSignal) => { if(!pokemonUrl) return; // url为空时不发起无效请求 setLoading(true); try { const response = await fetch(`${urls.baseUrl + pokemonUrl}`, { signal: abortSignal, }); const json = await response.json(); setData(json); } catch (error) { setError(error.message); } finally { setLoading(false); } }; useEffect(() => { const abortController = new AbortController(); fetchingPokemonAttributes(abortController.signal); return () => { abortController.abort(); }; }, [pokemonUrl]); return {data, error, isLoading}; };
内容的提问来源于stack exchange,提问作者Matko Milić
相关产品推荐
相关产品推荐

