I'm trying to use my custom hook when onPress is tapped, it receives a parameter but after calling it it returns invalid hook call. I want to call my UPDATED custom hook by calling a function that would pass the argument, I mean parameter, to my custom hook so it loads the chosen url.
My code:
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>
);
};
My custom hook:
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};
};
It's not working because your custom hook is not in the PokemonListItem
component's body. With current implementation, it's a bit tricky to call the fetchingPokemonAttributes
from the PokemonListItem
component.
Instead of calling another function to call the fetchingPokemonAttributes
, call it directly with onPress
action.
To achieve this, we need to export the fetchingPokemonAttributes
from the custom hook to use it in PokemonListItem
:
First, in the custom hook:
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};
};
Note: since the fetchingPokemonAttributes
need the url
, I removed the pokemonUrl
from the custom hook and pass it directly with the fetchingPokemonAttributes
function.
Note: you added a await
keyword in setData
method. it's redundant.
Second,, in the PokemonListItem
, we need to call fetchingPokemonAttributes
with onPress
action. (don't forget to pass the URL here)
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>
)
}
Now, with the onPress
action, the fetchingPokemonAttributes
will invoke and the custom hook returns data
, error
, isLoading
. Now time to use them in the PokemonListItem
with useEffect
hook.
As you see, I used some rules to check the conditions before updating the pokemon
, you can define your custom condition here according to your requirement and data
type.