Updating useEffect api call url with user inputs - reactjs

I'm working on a project, where I need to update a datachart with user inputted dates. I'm having trouble on how to update the url inside the useEffect hook. Here's my relevant code:
const finalUrl =`${apiUrl}id=${id}&timing=${time}&start=${finalStart}&end=${finalEnd}`;
console.log(finalUrl);
useEffect(() => {
axios
.get<AxiosResponse>(finalUrl, {
headers: {
"Content-Type": "application/json"
}
})
.then(response => {
setData(response);
})
.catch(error => {
console.log(error);
});
}, []);
console.log(data);
Everything looks good until i get to the axios call. I cannot get useEffect to use the updated url. Logging the response data just gives the same every time. All values inside "finalUrl" are coming from the user.

I'm going to assume that apiUrl and id never change, but that all the other things you're using in the API URL are inputs from the user.
If so, you need to rebuild the URL in the useEffect callback, and make the callback dependent on those user inputs, like this:
useEffect(() => {
const finalUrl =`${apiUrl}id=${id}&timing=${time}&start=${finalStart}&end=${finalEnd}`;
axios
.get<AxiosResponse>(finalUrl, {
headers: {
"Content-Type": "application/json"
}
})
.then(response => {
setData(response);
})
.catch(error => {
console.log(error);
});
}, [time, finalStart, finalEnd]);
The callback will be called again when time, finalStart, or finalEnd change.
Note that you also need to disregard or cancel previous requests when the dependencies change, even if the request hasn't been completed yet. I don't use axios but as I understand it has a "cancel/cancellation token" you can use for doing that. Here's what it would look like with fetch, which uses AbortController:
useEffect(() => {
const finalUrl =`${apiUrl}id=${id}&timing=${time}&start=${finalStart}&end=${finalEnd}`;
// Create the controller so we can cancel the request
const controller = new AbortControlller();
// Pass `signal` to fetch vvvvvvvvvvvvvvvvvvvvvvvvvvv
fetch<DataType>(finalUrl, {signal: controller.signal})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
return response.json();
})
.then(setData)
.catch(error => {
console.log(error);
});
// Return a cleanup callback
return () => {
// Cancel the request since its response would be out of date
controller.abrt();
};
}, [time, finalStart, finalEnd]);
console.log(data);

Related

React useEffect on [ ] adds duplicate items to the list [duplicate]

I'm trying fetching data in react. I call the fetch function only once but it's sending request multiple times but I don't know why. I looked other questions and tried their answers but none of them worked.
When I delete useEffect and leave the function alone, it sends a request once, but I think this is not the right way.
useEffect(() => {
fetchFunction();
}, [])
const fetchFunction =() => {
console.log("ldşsaşdlisaldi")
axios.get(
"someAPI",
{
headers: {
"Authorization" : localStorage.getItem("token")
},
credentials: 'include',
}
)
.then(res => res.json())
.then(
(result) => {
console.log(result)
setIsLoaded(true);
setTableData(result);
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}
Don't attempt to do any sort of "initial mount" check or "state" as this is considered anti-pattern. Don't try to "outsmart" React. The double-mounting is a way for the React.StrictMode component to help you see unexpected side-effects and other issues. You should implement a cleanup function to cancel any in-flight requests when the component unmounts. Use an abortController with the axios GET request.
Example:
useEffect(() => {
const controller = new AbortController(); // <-- create controller
fetchFunction({ controller }); // <-- pass controller
return () => controller.abort(); // <-- return cleanup function
}, []);
const fetchFunction = ({ controller }) => {
axios.get("someAPI", {
headers: {
"Authorization" : localStorage.getItem("token")
},
credentials: 'include',
signal: controller.signal // <-- pass signal to request
})
.then(res => res.json())
.then((result) => {
console.log(result);
setTableData(result);
})
.catch((error) => {;
setError(error);
})
.finally(() => {
setIsLoaded(true);
});
}
For more details and explanation see Fetching Data.

React fetch sending request multiple times

I'm trying fetching data in react. I call the fetch function only once but it's sending request multiple times but I don't know why. I looked other questions and tried their answers but none of them worked.
When I delete useEffect and leave the function alone, it sends a request once, but I think this is not the right way.
useEffect(() => {
fetchFunction();
}, [])
const fetchFunction =() => {
console.log("ldşsaşdlisaldi")
axios.get(
"someAPI",
{
headers: {
"Authorization" : localStorage.getItem("token")
},
credentials: 'include',
}
)
.then(res => res.json())
.then(
(result) => {
console.log(result)
setIsLoaded(true);
setTableData(result);
},
(error) => {
setIsLoaded(true);
setError(error);
}
)
}
Don't attempt to do any sort of "initial mount" check or "state" as this is considered anti-pattern. Don't try to "outsmart" React. The double-mounting is a way for the React.StrictMode component to help you see unexpected side-effects and other issues. You should implement a cleanup function to cancel any in-flight requests when the component unmounts. Use an abortController with the axios GET request.
Example:
useEffect(() => {
const controller = new AbortController(); // <-- create controller
fetchFunction({ controller }); // <-- pass controller
return () => controller.abort(); // <-- return cleanup function
}, []);
const fetchFunction = ({ controller }) => {
axios.get("someAPI", {
headers: {
"Authorization" : localStorage.getItem("token")
},
credentials: 'include',
signal: controller.signal // <-- pass signal to request
})
.then(res => res.json())
.then((result) => {
console.log(result);
setTableData(result);
})
.catch((error) => {;
setError(error);
})
.finally(() => {
setIsLoaded(true);
});
}
For more details and explanation see Fetching Data.

change api fetch into axios call

i am trying to change the api fetch into axios get method i dont know how to do that
const fetchApi = () => {
const request = getAllActivityData();
request
.api({
params: {
customer,
},
})
i want to call api like this using axios
i have added full code in codesandbox it will be helpfull if u can edit the codesand box and make it working
useEffect(() => {
const config = {
headers: {
Authorization: `token
},
};
axios.get("customer/get-all-activity-data/?customer=22", config)
.then((res) => {
console.log(res.data);
});
code sandbox
https://codesandbox.io/s/upbeat-jasper-2jmri?file=/src/App.js:3137-3298
what i have tryed the data is not showning but there are no error .
i am getting data in postman
https://codesandbox.io/s/gifted-montalcini-j7nv7?file=/src/App.js
Do you mean something like this, using async await...
const axiosCallFn = async () => {
let url = '...'
let config = {
headers: {
token: '...'
}
}
try {
let resp = await axios.get(url, config)
return resp.data
} catch(e) {
throw e
}
}
// import the function into your component and use it like so
axiosCallFn()
.then((data) => {
// your functionality here.
})
.catch(() => {
// your error functionality here.
})
and then you can call your axiosCallFn in your useEffect.

update the state of my component with the response data after Post request with axios

I'm trying to update the state of my component with the response data after Post request with axios but it returns an empty array when I log out the updated state with console.log(), but shows the response.data information received with .then in axois in the broswer console. Please help me out
Code starts here
const [offers, setOffers] = useState({});//THIS IS THE STATE
const search async (e) => {
e.preventDefault();
const options = {
url: "localhost:8080/api/search",
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json;charset=UTF-8",
},
data,
};
axios(options)
.then((response) => {
console.log(response.data.data);// THIS RETURNS OBJECT DATA GOTTEN FROM THE SERVER AFTER POST REQUEST
setOffers(response.data.data); //IT DOES NOT UPDATE WITH RESPONSE DATA
console.log(offers); = IT RETURNS AND EMPTY ARRAY
})
.catch(function (error) {
if (error.response) {
setValerr(error.response.data.errors);
console.log(error.response);
}
});
};
thanks in advance
In react, setState is asynchronous, so when you call "setOffers" it is an asyncronous action.
Therefore when you call console.log, offers might not be updated yet.
You can read more about it here:
https://reactjs.org/docs/faq-state.html#when-is-setstate-asynchronous
To listen to the value of "offers" you might need to use useEffect
An example
const [offers, setOffers] = useState({}) //THIS IS THE STATE
const search = async (e) => {
e.preventDefault()
const options = {
url: 'localhost:8080/api/search',
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json;charset=UTF-8',
},
data,
}
axios(options)
.then((response) => {
console.log(response.data.data) // THIS RETURNS OBJECT DATA GOTTEN FROM THE SERVER AFTER POST REQUEST
setOffers(response.data.data) //IT DOES NOT UPDATE WITH RESPONSE DATA
console.log(offers)
})
.catch(function (error) {
if (error.response) {
setValerr(error.response.data.errors)
console.log(error.response)
}
})
}
useEffect(() => {
// This should log offers to the console if it has been set
if(offers) {
console.log(offers)
}
}, [offers])

How to re-render a page by updating the state In React using functional component.?

I am dealing with POST and GET request.
When user makes a POST request data gets stored in the DB.
In GET request I am retrieving the data from DB.
In my useEffect I am using the GET request to get the data. It works only when page renders for the first time. It does not update the state whenever I make a POST request . I have to manually refresh the page to get the new data. When I put the state in my dependency it keeps making the fetch request as long as I am on that component . Below is my code..
Post Request
The post request is being made from child component.
const addFolder = async() => {
if (!folderName) {
alert("Folder Name Required");
} else {
const projectId = props.match.params.projectId
console.log("Project Id ==> ",projectId) //use projectId to make a call to the server..
console.log(folderName)
await fetch(`http://localhost:8080/mirFolder/new/${projectId}`,{
method:"POST",
body: JSON.stringify({
"title":folderName,
}),
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}).then((res)=>{
console.log(res)
// window.location.reload()
return res.json();
}).catch((err) =>{
console.log(err)
})
}
}
GET request function
const [state, setstate] = useState([]);
useEffect(() => {
const token = isAuthenticated().token;
const projectId = props.match.params.projectId;
getMirFolderbyProject(token, projectId).then((data) => {
if (data.error) {
console.log(data.error);
} else {
console.log("data ==>", data);
setstate(data);
}
});
}, []);
GET fetch Api
export const getMirFolderbyProject = (token, projectId) =>{
return fetch(`http://localhost:8080/mirFolder/by/${projectId}`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
})
.then((response) => {
return response.json();
})
.catch((err) => {
console.log(err);
});
}
This is because when a server gets a POST it will not serve new data, if you want the new data to be displayed after the POST request make sure to serve the new data to the client in the POST request.
you should fill your dependencies array with the variables which on change you would want re-render the component
const [state, setstate] = useState([]);
useEffect(() => {
const token = isAuthenticated().token;
const projectId = props.match.params.projectId;
getMirFolderbyProject(token, projectId).then((data) => {
if (data.error) {
console.log(data.error);
} else {
console.log("data ==>", data);
setstate(data);
}
});
}, [token , projectId]);
As #Klump said, when you made the POST request and update the data in DB, you again need to make a GET request instead of fetching updated data fetched from the POST response in order to keep the consistency.
For this, once the POST request promise resolved, you can use an additional fetching state in order to make a GET request.
Please provide your complete implementation containing both GET and POST requests with all the necessary components to further work on it.

Resources