I have this update form for a place and I fetch its data from the backend to add initial inputs in useEffect but I got this error
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
I know the problem is related to unmounted the component before update the state but I try many solutions but not working. Anyone have an idea how to fix that
const UpdatePlace = () => {
const placeId = useParams().pId;
const [loadedPlace, setLoadedPlace] = useState();
// const [isLoading, setIsLoading] = useState(true);
const { error, sendRequest, clearError } = useHttpClient();
const [isLoading, formState, inputHandler, setFormData] = useForm(
{
title: {
value: "",
isValid: false,
},
description: {
value: "",
isValid: false,
},
},
true
);
useEffect(() => {
const fetchPlace = async () => {
try {
const res = await sendRequest(`/api/places/${placeId}`);
await setLoadedPlace(res.data.place);
setFormData(
{
title: {
value: res.data.place.title,
isValid: true,
},
description: {
value: res.data.place.description,
isValid: true,
},
},
true
);
} catch (err) {}
};
fetchPlace();
}, [sendRequest, placeId, setFormData]);
if (!loadedPlace && !error) {
return (
<div className="center" style={{ maxWidth: "400px", margin: "0 auto" }}>
<Card>
<h2>No place found!</h2>
</Card>
</div>
);
}
const placeUpdateSubmitHandler = (e) => {
e.preventDefault();
console.log(formState.inputs, formState.isFormValid);
};
return (
<>
{isLoading ? (
<LoadingSpinner asOverlay />
) : error ? (
<ErrorModal error={error} onClear={clearError} />
) : (
<>
<Title label="Update place" />
<form className="place-form" onSubmit={placeUpdateSubmitHandler}>
<Input
element="input"
type="text"
id="title"
label="Update title"
validators={[VALIDATOR_REQUIRE()]}
errorText="please enter valid title"
onInput={inputHandler}
initialValue={loadedPlace.title}
initialValid={true}
/>
<Input
element="textarea"
id="description"
label="Update description"
validators={[VALIDATOR_REQUIRE(), VALIDATOR_MINLENGTH(5)]}
errorText="please enter valid description (min 5 chars) "
onInput={inputHandler}
initialValue={loadedPlace.description}
initialValid={true}
/>
<Button type="submit" disabled={!formState.isFormValid}>
Update place
</Button>
</form>
</>
)}
</>
);
};
This error means that your request completes after you have navigated away from that page and it tries to update a component that is already unmounted. You should use an AbortController to abort your request. Something like this should work:
Edit: Fix undefined obj key/value on render
The above warning will not stop your component from rendering. What would give you an undefined error and prevent your component from rendering is how you initiate the constant loadedPlace. You initiate it as null but you use it as an object inside your Input initialValue={loadedPlace.title}. When your component tries to do the first render it reads the state for that value but fails to locate the key and breaks.
Try this to fix it:
Always make sure that when you use an object you don't use undefined keys upon render.