Lara
Lara

Reputation: 3021

Custom react hook to fetch data is not giving data on second hit

I have a below custom useEffect hook to fetch data from API.

export const useGetData = (url, body, isNew) => {
const [state, setState] = useState([]);
const [error, setError] = useState({});

useEffect(() => {
    if (isNew) {
        fetch(url, {
            method: 'Post',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(body)
        }).then(response => response.json())
            .then(apiData => {
                   setState({ apiData });
            }).catch(error =>
                console.error('Error:', error)
            );
        setError(error);
        console.log("Error: " + error);
        return error;
    }
}, []);
return state;
}

Now, in my component i am trying to use above hook after a handleInputChanges event as below

let dt = {};
const [inputParam, setInputParam] = useState({
    FirstName: 'Tom',
    LastName : 'Harris'
});

const handleInputChanges = (params) =>{
    setInputParam(params);
};

dt = useGetData (url, inputParam, true);

With above code, i am able to hit useGetData custom hook but, hook is not calling the API url and hence data dt is not updating. What's wrong? Kindly suggest.

Upvotes: 0

Views: 675

Answers (2)

Fred A
Fred A

Reputation: 1764

You're not passing 2nd argument properly inside the useEffect.

Make it like this

useEffect(() => {
    if (isNew) {
        fetch(url, {
            method: 'Post',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(body)
        }).then(response => response.json())
            .then(apiData => {
                   setState({ apiData });
            }).catch(error =>
                console.error('Error:', error)
                setError(error); // Save your error inside the catch block
            );

        // return error; <-- Do not return anything that isn't used for useEffect cleanup! Use return only for cleanup, like unsubscribing API. 
    }
}, [isNew]); <--- This will ensure that everytime isNew changes, it will run the useEffect again. 

But you might wanna change the dependency to other variable, as isNew is a boolean, therefore i think it might not work if on the next call, you're passing true again.

You can use the URL as a dependency to the useEffect, so that on every new URL, it will run the call inside useEffect.

Upvotes: 1

Ayushya
Ayushya

Reputation: 1920

You are using empty array in second parameter of useEffect this won't update when props change. This is similar to componentDidMount. You need to either pass on the props like [url, body, isNew] or dont pass second parameter in useEffect at all.

export const useGetData = (url, body, isNew) => {
const [state, setState] = useState([]);
const [error, setError] = useState({});

useEffect(() => {
    if (isNew) {
        fetch(url, {
            method: 'Post',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(body)
        }).then(response => response.json())
            .then(apiData => {
                   setState({ apiData });
            }).catch(error =>
                console.error('Error:', error)
            );
        setError(error);
        console.log("Error: " + error);
        return error;
    }
}, [url, body, isNew]);
return state;
}

Upvotes: 1

Related Questions