Reputation: 8597
I'm getting the Rendered more hooks than during the previous render
error in my react native application in this screen:
const HomeScreen = props => {
const [refreshing, setRefreshing] = useState(false);
if (props.data.loading) { // error shows its located here
return <Text>Loading...</Text>;
}
const onRefresh = useCallback(() => {
setRefreshing(true);
wait(2000).then(() => setRefreshing(false));
}, [refreshing]);
return (
<View style={styles.container}>
<FlatList
data={props.data.sample}
renderItem={({item}) => <Card {...item} user={props.data.user} />}
keyExtractor={item => item._id}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}
/>
</View>
);
};
But when I move the useState
below the if-statement:
const HomeScreen = props => {
if (props.data.loading) { // error shows its located here
return <Text>Loading...</Text>;
}
// moved here, change in the order of hooks...
const [refreshing, setRefreshing] = useState(false);
const onRefresh = useCallback(() => {
setRefreshing(true);
wait(2000).then(() => setRefreshing(false));
}, [refreshing]);
I get a Warning:
Warning: React has detected a change in the order of Hooks called by "HomeScreen". This will lead to bugs and errors if not fixed...
I get this error when my app hot reloads, but then when I Dismiss the warning and then force reload it doesn't appear. I just want to make sure that moving this below the if-statement is okay.
Also, I don't know why moving the useState will fix the original error message of rerendering?
Upvotes: 3
Views: 4602
Reputation: 2452
Well, the error is obvious. Only useState
is called when loading
is true, and both useState
and useCallback
are called when it's not, so react complains about the number of hooks being inconsistent. The fix is most likely a fluke. This time no hooks are called when loading
is true, and both of them are rendered when it's not. React's source code probably doesn't make the "number of hooks rendered" check if that number is zero initially, hence no error.
As the warning tells you, conditionally calling hooks (writing a return statement before any hook) is a bad idea. It might not break you app in this particular instance, but it's overall a bad practice. The hooks are called on every render and react needs to keep track of them properly.
I would put all the hooks (in this case both useState
and useCallback
) BEFORE the conditional return. I don't see any reasons not to.
Upvotes: 3