5arg
5arg

Reputation: 39

Using history.push() re-renders current component

I have a component that gets a value from current location state and passes it down to child components.

interface RequestProcessingLocationState {
  request: RequestType; 
}
function RequestProcessing() { 
    const location = useLocation<RequestProcessingLocationState>();
    return (
     <div>
         <RequestDetails
             processId={location.state.request.processId}
             requestTitle={location.state.request.title}
         />
         <RequestForm request={location.state.request} />
     </div>
    ); 
}

One of the child components has a form that calls a REST endpoint and processes the request.

function RequestForm ({ request}: RequestFormPropsType): ReactElement {
    ... 
    const history = useHistory();
    useEffect(() => {     
        axiosInstance.get(/request/${request.id}/form) 
        .then((result) => {
             setForm(result.data);       
        }) 
        .catch((error) => {         
            console.log(error);       
     });   }, [request]);

const handleSubmit = ({ formData }: any) => { 
    axiosInstance.put(/request/process/${request.id}, formData)       
    .then(() => { 
        message.success(t("request-success")); 
        history.push("/requests); 
        })       
        .catch((error) => { 
            console.log(error.response); 
        });
};
    return ( ...)
}

The problem occurs when the handleSubmit method is called, specifically when the history.push() is executed. For some reason the useEffect() method of RequestForm component is executed once again, and the axios call throws an error because the request has already been processed.

My guess is that when the location is changed, the component is immediately updated because the request in dependency array comes from location state.

Is there any way to avoid this behaviour?

Upvotes: 1

Views: 147

Answers (3)

Cuong DaoVan
Cuong DaoVan

Reputation: 342

I think because of your request dependency, you need not pass the dependency in useEffect because it's prop. use Like this:

  useEffect(() => {     
    request && axiosInstance.get(/request/${request.id}/form) 
    .then((result) => {
         setForm(result.data);       
    }) 
    .catch((error) => {         
        console.log(error);
  // remove warning
  // eslint-disable-next-line react-hooks/exhaustive-deps
 });   }, []);

it just call once when component is mounted

Upvotes: 1

Moukim hfaiedh
Moukim hfaiedh

Reputation: 409

try adding a second parameter to the useEffect hook an empty array like that .

useEffect(() => {
    // Run! Like go get some data from an API.
  }, []);

Upvotes: 0

maya_nk99
maya_nk99

Reputation: 502

This is because of the submission of form by default. To prevent this in your submit function handleSubmit you have to add event.preventDefault();.

Upvotes: 0

Related Questions