使用参数无效的 Hook 调用来响应本机自定义 Hook 调用

问题描述 投票:0回答:2

我尝试在点击 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};
};
reactjs react-native
2个回答
0
投票

问题

它不起作用,因为您的自定义挂钩不在

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
类型在此处定义自定义条件。


0
投票

你不能打电话

const {data, isLoading} = usePokemonAttributes(chosenPokemonUrl);
在 pokemonsData const 中,你必须在 PokemonListItem 中调用它

© www.soinside.com 2019 - 2024. All rights reserved.