Axios call inside an axios response - reactjs

I'm having issue when I try to do an axios call whithin the scope of the response
const url = 'http://localhost:8000/session/';
axios.get(url).then(response => {
console.log(response)
const sessionEnCours = response.data.results.filter(session => session.fin_session == null).map(session => {
axios.get(session.client).then(client => {
session.client = `${client.prenom} ${client.nom}`
})
return session
})
sessionEnCours.map(session => console.log(session))
setSession(sessionEnCours)
})
}, []);
I have a Django API, so I have hyperlink models and get url as a foreign key. Whenever I'm trying to replace this url with the customer name with my little trick, it is not modified.
Thank you for your help

Related

"Cannot read property 'issues' of undefined" Reactjs

I am using gitbeaker to get a project from gitlab API, after fetching the project, I used useState to save the project object, now I want to fetch another API whose URL is in that object, but whenever I try to access that URL, an error appears "Cannot read property 'issues' of undefined".
Here's my code:
const [project, setProject] = useState<any>({});
const api = new Gitlab({
host: "https://example.com",
token: "my token",
});
useEffect(() => {
(async () => {
const projectsPromises = await api.Projects.all().then((allprojects) => {
return allprojects;
});
Promise.all(projectsPromises).then((data) => {
setProject(data.find((element) => element.id === 338));
});
})();
return () => {};
}, []);
console.log(project);
console.log(project._links.issues);
fetch(project._links.issues).then((res) => console.log(res));
console.log(project); gives me {} and after some time it prints the object, that's why when I try to use project._links.issues it is undefined as I think it isn't resolved yet but I don't know how to make it work.
I solved it by fetching the data in the useEffect hook and saving the response of the api in the state so that I can access it later in my code, like that
const [issues, setIssues] = useState<any>([]);
Promise.all(projectsPromises).then((data) => {
const celoProject: any = data.find((element) => element.id === 338);
setProject(celoProject);
const projectIssues = fetch(celoProject._links.issues)
.then((res) => res.json())
.then((allIssues) => {
setIssues(allIssues);
});
});
If someone has a better way or an explanation why I couldn't access it outside the useEffect, please tell me.
Anything inside the useEffect hook will only execute when the page first loads (because you provided an empty array as the second argument). Anything outside of it will execute on every render (every time props or state changes). That is why it logs {} the first time because the effect is asynchronous and hasn't completed before the component is rendered.
You should run the second fetch in the useEffect hook after the first API request completes. Need more information to determine what exactly is happening beyond this.
const [project, setProject] = useState<any>({});
const api = new Gitlab({
host: "https://example.com",
token: "my token",
});
useEffect(() => {
(async () => {
const projectsPromises = await api.Projects.all().then((allprojects) => {
return allprojects;
});
Promise.all(projectsPromises).then((data) => {
const projectResponse = data.find((element) => element.id === 338)
setProject(projectResponse)
fetch(projectResponse._links.issues).then((res) => {
console.log(res)
// Do something with this response
});
});
})();
return () => {};
}, []);
console.log(project);
console.log(project._links.issues);

How to get updated data which is posted as soon as the POST request is called? AXIOS

I have a scenario wherein according to the course_id, I add modules into it.
Now whenever I add a new module, I have to refresh the page to get the newly added module along with the old ones. How do I fetch the data posted(new ones) as soon as the request is called.
const fetchModule = () => {
useEffect(() => {
axios.get(`http://localhost:8083/getmodules/${course_id}`)
.then(res => {
updateModule(res.data)
})
.catch(error => {
console.log(error)
});
}, [course_id]);
}
const submitHandler = (e) => {
const course = { course_id, course_name };
const formdata = { module_id, module_type, module_name, duration, course };
axios.post("http://localhost:8083/createmodule", formdata)
.then( res =>
{
console.log(res.data);
fetchModule();
})
}
Now the fetchModule function fetches the module, so as soon as we post the data in then I call the fetchModule, but this doesnt seem to work. Please help. Thank you in advance :)

Login status in React

I created authorization in javascript. Then if success login I redirect to React project with url parameter http://localhost:3000/?phoneNum=%2B77072050399
Then in React I get userId by using the passed url parameter => phoneNumber using axios.
I realized it in App.js. Code below:
let url = window.location.href;
let params = (new URL(url)).searchParams;
const userPhoneNum = encodeURIComponent(params.get('phoneNum'));
const [userToken, setUserToken] = useState(null);
const getUserToken = async() => {
try {
const data = await axios
.get(`https://stormy-escarpment-89406.herokuapp.com/users/getToken?phone_number=${userPhoneNum}`)
.then(response => {
setUserToken(response.data);
})
.catch(function(error) {
console.log('No such user! Error in getting token!');
});
} catch (e) {
console.log(e);
}
}
useEffect(() => {
getUserToken();
console.log(userToken);
}, userToken);
So, when I go to next page localhost:3000/places, it is requesting for userToken again with parameter null, because there is no param phoneNum.
How to make it to request only one time and save the userId after it is taken in main page. So, then only when I click LogOut button reset the variable where userID is saved.
If you want to do that without using any third party libraries you can use browser's in built storage api
So, when you receive the token, you can store that in the local storage of the browser using localstorage.setItem and later when you wan to see if the token is there or not just read from there using localStorage.getItem
const getUserToken = async() => {
try {
const data = await axios
.get(`https://stormy-escarpment-89406.herokuapp.com/users/getToken?phone_number=${userPhoneNum}`)
.then(response => {
setUserToken(response.data);
Storage.setItem('token',JSON.stringify(response.data))
})
.catch(function(error) {
console.log('No such user! Error in getting token!');
});
} catch (e) {
console.log(e);
}
}
For Logout you can simply remove the token using localStorage.removeItem
You can easily achieve this by using the react-cookie library
npm i react-cookie
Can be easily implemented in your code by
cookies.set('key', value, { path: '/' });
cookies.get('key')
After getting the userNumber form the param
const userPhoneNum = encodeURIComponent(params.get('phoneNum'));
cookies.set('userphoneNum', userPhoneNum);
View the documentation for more information
https://www.npmjs.com/package/react-cookie

Connect Firebase Auth with Firestore in React

I'm trying to figure out how to connect users with data in my firestore. I didn't find anything about how to do it in React.
My idea, in the register page of my app, is:
async function register() {
try {
await auth.createUserWithEmailAndPassword(email, password).then(data => {
auth.currentUser.updateProfile({
displayName: name
})
db.collection('usersdata').doc(data.user.uid).set({nome: name})
props.history.replace('/success')
})
} catch(error) {
alert(error.message)
}
}
In this way I'm creating a new user and also a new entry in my "usersdata" collection. That entry has the same ID and the same name of the user.
After the login I can get the active user name using:
const userName = getCurrentUsername()
function getCurrentUsername() {
return auth.currentUser && auth.currentUser.displayName
}
All of this is working. But here it comes my problem:
I would like to add new data to the current user, for example "age" and "nationality".
But I don't know how to exactly get access to that user from firestore instead of auth.
And I also need to return only his data. Then, after a research, I need to return data from all users, and I guess that is the method:
const [datidb, setDatidb] = useState([])
useEffect(() => {
const fetchData = async () => {
const data = await db.collection('usersdata').get()
setDatidb(data.docs.map(doc => doc.data()))
}
fetchData()
}, [])

Changing url based on id and getting values from local storage. ReactJS

I am currently trying to access the logged in user's role by getting a value stored in localStorage, then based on that value I wanna set up my url and perform a fetch request. All of this is happening inside a ContextProvider.
My issue is that my fetch request is firing before I can obtain the value stored in localStorage.
Here is how I construct my url:
const [userRole, setUrerRole] = useState(0);
const [url, setUrl] = useState('');
let userID = localStorage.getItem('userID');
if (userID === 3){
setUrl("https://api.myjson.com/bins/00666")
}else if(userID === 1){
setUrl(process.env.REACT_APP_API_URL+"/api/v111/someexampleendpoint")
}
and I use the hook,
useMemo(() => {
fetch(url)
.then(response => response.json())
.then(response => {
setUserDetails(response);
})
.catch(error => console.log(error));
}, []);
Now the way I tried to do it originally is by creating a promise and chaining the functions but it didn't work.
function grabUserdStoredID(){
let userID = localStorage.getItem('userID');
if (userID === 3){
setUrl("https://api.myjson.com/bins/00666")
}else if(userID === 1){
setUrl(process.env.REACT_APP_API_URL+"/api/v111/someexampleendpoint")
}
return Promise.all
}
grabUserdStoredID.then(
useMemo(() => {
fetch(url)
.then(response => response.json())
.then(response => {
setUserDetails(response);
})
.catch(error => console.log(error));
}, []);
)
but it said that I cannot fire the hook in that way...
How can I call a fetch request inside a context after I've obtained
values from localStorage?
You have a lot of things going wrong here. I'm going to point out a few of them and give you an alternative structure at the end.
Your url can be derived from your state, so don't also store that in state.
Do not useMemo for an api call. useMemo is for caching computed values on render to prevent you from having to do it again unnecessarily. In this case you do want to put the results of your api call in state.
Fetch api calls with useEffect which then calls a state setter function after the fetch promise resolves. This way you can easily control the timing of the api calls with the dependency array.
localStorage.getItem() is not a problem here. It's synchronous api that returns a value immediately.
Putting this together, you end up with something like:
function SomeComponent() {
const [userDetails, setUserDetails] = useState()
let userID = localStorage.getItem("userID")
useEffect(() => {
let url
if (userID === "3") {
url = "https://api.myjson.com/bins/00666"
} else if (userID === "1") {
url = process.env.REACT_APP_API_URL + "/api/v111/someexampleendpoint"
}
fetch(url)
.then(response => response.json())
.then(response => {
setUserDetails(response)
})
.catch(error => console.log(error))
}, [userID])
return <div>Content Here</div>
}

Resources