Why does calling setState inside my component cause infinite re-render but calling setState inside useQuery onSuccess callback work just fine❓ #3226
-
Hi all,
Checking myself 😅
Codesandbox: https://codesandbox.io/s/condescending-butterfly-71o4r const defaultItem = { name: "default" }
export default function App() {
const [items, setItems] = React.useState<Item[]>([ defaultItem ]);
const [itemToFetch, setItemToFetch] = React.useState<string>("apple");
const handleButtonClick = React.useCallback((event: any) => {
const buttonValue = event?.target?.value;
setItemToFetch(event?.target?.value);
}, []);
// Approach 1: calling setItems outside of `onSuccess` callback
// Imagine when calling this that "Approach 2" is commented out...
const dataInfo = useGetData(itemToFetch);
const newItem = dataInfo.data || defaultItem;
setItems([...items, newItem]); // ❌ calling `setItems` here causes component to infinitely re-render
// Approach 2: calling setState inside `onSuccess`
const dataInfo = useGetData(itemToFetch, (onSuccessData) => {
const newItem = onSuccessData;
setItems([...items, newItem]); //✅ calling `setItems` here doesn't cause component to re-render infinitely
});
return (
<button onClick={handleButtonClick} value="..some value">..some value</button>
<ul>
{items.map((item, i) => {
return <li key={i}>{item.name}</li>;
})}
</ul>
)
} 00example.mp4 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
because just re-rendering your component will not trigger So the flow is:
You have also identified correctly why it doesn't work during render - that also violates the rule of react that render functions have to be pure. You can call However, you usually don't need to call |
Beta Was this translation helpful? Give feedback.
because just re-rendering your component will not trigger
onSuccess
again.onSuccess
is tied to data fetching, so it will only be called when a request is successfully made. Conceptually,onSuccess
isPromise.then
,onError
isPromise.catch
andonSettled
isPromise.finally
.So the flow is:
You have also identified correctly why it doesn't work during render - that also violates the rule of react that render fun…