React useRef() is being useless. Can't prevent re-fetching on form clear

I have a vehicle update form component with a 'clear form' button. The button resets the useState form object field values to nothing again, and due to this state change, React of course is re-rendering the entire component, which is fine for seeing blank form fields again, however this re-render is also causing fetch api's (my fetchInventory and fetchSteps) to also be re-run, which is unnecessary since the data from the fetch api's is already saved (from the component's first mounting/rendering). To avoid re-running these fetch calls upon re-render, I set some useRef variables - stepsFetched & dataFetched - to be false initially, but then set to 'true' after the first running of each fetch call (once I have the data), and then additionally, I am testing their truthness/falseness inside of the fetch function, prior to the call, to know whether to actually make the fetch call:
const fetchSteps = async () => {
if (stepsFetched.current) {
console.log("stepsFetched is true");
return;
}

try {
const response = await axios.get(`${apiUrl}/api/steps`);

const fetchInventory = async () => {
if (dataFetched.current) {
console.log("dataFetched is true");
setLoading(false);
return;
}
try {
const response = await axios.get(`${apiUrl}/api/admin/vehicle/list`);
};
const fetchSteps = async () => {
if (stepsFetched.current) {
console.log("stepsFetched is true");
return;
}

try {
const response = await axios.get(`${apiUrl}/api/steps`);

const fetchInventory = async () => {
if (dataFetched.current) {
console.log("dataFetched is true");
setLoading(false);
return;
}
try {
const response = await axios.get(`${apiUrl}/api/admin/vehicle/list`);
};
The useRefs however, are not maintaining their being set to 'true' after the initial mounting/rendering of the component, into the second rerender, so as to trigger these if() statements and prevent another fetch. Am I doing something else wrong here? Shouldn't they still be 'true' on a re-render? Are the 'await' or 'async' keywords here causing the problem possibly?
3 Replies
missymae
missymae2mo ago
It's a dense chunk of code, and with nothing to experiment on, I'm shooting in the dark - sorry if I mislead or waste your time. I think about useMemo and useCallback in this situation. I also would have thought this is a single component problem React 19 would handle with the new compiler, which I haven't experienced. The
React.useState()
React.useState()
style is outdated, so maybe you want to review new React docs and see if upgrading would solve the problem for you.
glutonium
glutonium2mo ago
i myself is new to react but here's an abstract code on how I'd do it, which is same as what u described. I can't see thw code cause m on mobile
const isFecthedAlready = useRef(false);

useEffect(() => {
if(isFetchedAlready) { return }

handleFetch();
isFetchedAlready.current = true;
}, []);

return (
<form>
{/* other elemets */}
<button
id="close"
onClick={() => setFormData()}
> Clear Form </button>
</form>
)
const isFecthedAlready = useRef(false);

useEffect(() => {
if(isFetchedAlready) { return }

handleFetch();
isFetchedAlready.current = true;
}, []);

return (
<form>
{/* other elemets */}
<button
id="close"
onClick={() => setFormData()}
> Clear Form </button>
</form>
)
thethingisback
thethingisback2mo ago
thank you. I tried both useCallback and useMemo and still seeing the fetch call being re-run, but I've lightened significantly the fields being retrieved from the table, so I think I'm just going to roll with that for now. I'll have to come back and play with this more later.
Want results from more Discord servers?
Add your server