React Native - I want to set my session state first before I call my API - reactjs

I am new to React Native.
If someone can help me then would be great.
How I can set my session state first from AsyncStorage before it goes for API call. Because this API call required sessionId (UserId) so it can return only those data which belong to this userId.
The issue I am currently facing is when API calls for the data it is calling with null seesionId instead of some value which I am getting from AsyncStorage because both methods (settingSession, InitList ) are async.
const [sessionId, setSessionId] = useState(null);
const settingSession = async () => {
await AsyncStorage.getItem('userId').then(val => setSessionId(val));
}
useEffect(() => {
settingSession(); // Setting sessionId
InitList(); // Calling API which required session value
}, []);
const InitList = async () => {
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
try {
// getting sessionId null instead of value from AsyncStorage
const response = await fetch("http://127.0.0.1:8080/skyzerguide/referenceGuideFunctions/tetra/user/" + sessionId, requestOptions)
const status = await response.status;
const responseJson = await response.json();
if (status == 204) {
throw new Error('204 - No Content');
} else {
setMasterDataSource(responseJson);
}
} catch (error) {
console.log(error);
return false;
}
}

I'm thinking of two possible solutions:
Separate InitList() into a separate useEffect call, and put sessionId in the dependency array, so that the API call is only made when the sessionId has actually been updated:
useEffect(() => {
settingSession(); // Setting sessionId
}, []);
useEffect(() => {
InitList(); // Calling API which required session value
}, [sessionId]);
Wrap both functions in an async function within the useEffect call, and call them sequentially using await:
useEffect(() => {
const setSessionAndInitList = async() => {
await InitList(); // Calling API which required session value
await settingSession(); // Setting sessionId
}
setSessionAndInitList()
}, []);
Let me know if either works!

Related

Handling axios errors in child components?

My React app has an api client component which handles axios calls to the back end. So, in the api component I have:
async function getData(path: string, params?: any) {
const object: AxiosRequestConfig = {
...obj,
method: 'GET',
headers: {
...obj.headers,
},
params,
};
const response: AxiosResponse = await axios.get(
`${baseUrl}${path}`,
object
);
return response;
});
}
(obj contains the headers and is defined earlier in the file; baseUrl is a constant which I import).
So, if I have a useEffect to retrieve data from the endpoint '/user/{userId}' whenever the state variable userId changes, I do this:
React.useEffect(() => {
const controller = new AbortController();
const getData = async () => {
try {
const url = `user/${userId}`;
let res = await Client.getData(url, {
signal: controller.signal,
});
... Do things with results ...
} catch (e) {
// Show error
if (!controller.signal.aborted) console.log('Error: ', e);
}
};
getData();
return () => {
controller.abort();
};
}, [state.userId]);
I'm just a bit confused about how errors will be handled in this code. So, if there's an error when the axios call is made (eg no network connection, the endpoint is wrong, or the user isn't found or whatever) will the catch block get called in the getData function? Or do I need a try...catch in the api component too?

GitHub API getRepos async request turn back a promise instead of an array of repos

I have a problem with async request return. It returns me back a Promise instead of data!!
So i tried to process data variable a second time but it did not work. I exported it as it needs, created initial state for repo=[], passed in to the reducer...
gitContext.jsx
const getRepos = async (login) => {
setLoading();
const params = new URLSearchParams({
sort:'created',
per_page:10
})
const response = await fetch(`http://api.github.com/users/${login}/repos?${params}`)
if (response.status === 404) {
window.location = './notfound'
} else {
const data = await response.json();
console.log(data);
dispatch({
type: 'GET_REPOS',
payload: data
})
}
}
Here is the function call from User.jsx
const { getUser, user, isLoading, repos, getRepos } = useContext(GitContext);
const params = useParams()
useEffect(() => {
getUser(params.login);
// console.log(getRepos(params.login?.repos))
getRepos(login?.repos);
}, [])

ReactJS: Wait for data before saving to useState [duplicate]

This question already has answers here:
React Hooks: how to wait for the data to be fetched before rendering
(4 answers)
Closed 1 year ago.
i have the following problem:
I'm fetching data (true or false value) from my database and want to save it to a useState.
I'm using async/await for the fetch. Because of that, the value saved to my state is undefined.
Here is my code:
const [myState, setMyState] = useState();
useEffect(() => {
myFunction()
async function myFunction () {
const req = await fetch("http://localhost:3001/api/getdata", {
headers: {
"x-access-token": sessionStorage.getItem("token")
}
})
const data = await req.json()
console.log("fetched data value: " + data)
// This is undefined in the console
setMyState(data)
// I already tried this, but await does not affect a setState
// const blah = await setMyState(data)
}
}, [])
How can i wait for the data to be fetched before saving it to the state?
Thanks for helping.
Since you have an async function, you can use then() promise handlers to only set the state once the data is fetched. Here's an example:
const [myState, setMyState] = useState();
useEffect(() => {
myFunction()
async function myFunction () {
// Call then() after using fetch to pass the result into a callback that saves state
fetch("http://localhost:3001/api/getdata", {
headers: {
"x-access-token": sessionStorage.getItem("token")
}
}).then(
(response) => response.json()
).then(
(data) => setMyState(data)
)
}
}, [])
Check out the official web api for fetch: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
What you have should work but you should set an initial value for your useState to an empty array or what ever it is your data will eventually be or at least null or undefined explicitly that way you know what state it is before its loaded
Below is stackblitz with a working example
https://stackblitz.com/edit/react-pimpje?file=src/App.js
function App() {
const [myState, setMyState] = React.useState(null);
React.useEffect(() => {
async function myFunction() {
/**
* https://apipheny.io/free-api/
*/
const req = await fetch('https://api.publicapis.org/entries');
const data = await req.json();
console.log('fetched data value: ', data);
setMyState(data);
}
myFunction();
}, []);
return <div>{myState && <pre>{JSON.stringify(myState, null, 2)}</pre>}</div>;
}

Read the setState value immediately after setting in useEffect React

I want to fetch info from the API in useEffect, set it using setState and immediately use it for further filtering.
the code looks like this:
const[usersInfo, setUsersInfo] = setState('')
useEffect(()=>{
async function fetchUsers(){
const response = await fetch(`http://localhost:8083/api/patient/findAll`);
const json = await response.json();
setUsersInfo(json)
}
fetchUsers()
console.log('users info', usersInfo)
},[])
I tried to pass the dependency for usersInfo but then it is running in loop.
What can I do it to prevent this behavior?
You need to add a second useEffect that detects changes to usersInfo.
const [usersInfo, setUsersInfo] = setState("");
useEffect(() => {
async function fetchUsers() {
const response = await fetch(`http://localhost:8083/api/patient/findAll`);
const json = await response.json();
setUsersInfo(json);
}
fetchUsers();
// console.log("users info", usersInfo); // commenting out this code since it will always print empty string
}, []);
useEffect(() => {
if(usersInfo !== ""){
// Do stuff here with usersInfo
}
}, [usersInfo]);

Getting a return value from axios function in reactJS

I am new to reactJS , my problem is that I want to assign my varaiable a value that has been returned from a axios function.When I do this, I get undefined value for u1.
function getUsername(userid){
var user = ''
axios.post('/api/getuserdata' , {_id:userid}).then(res=>{
console.log(res.data)
const userdata = res.data[0]
user = userdata.username
}).catch(err=>{
console.log(err)
})
return user
}
const u1 = getUsername(id)
The reason your code doesn't work is that the POST request handled by axios is async, your getUsername function won't wait for that request to resolve and return user immediately after it's called.
The simplest solution is that make your getUsername async and call it in another async function, or if you want to use the result returned from POST request for some other stuff, you can store it as state in React, it would be better.
You can use something like this:
const getUsername = async (userid) => {
try {
const response = await axios.post("/api/getuserdata", { _id: userid });
const userdata = response?.data?.[0]?.username || "";
return userdata;
} catch (error) {
console.log(`error`, error);
}
};
// in another function
const doSomethingWithUsername = async (id) => {
const username = await getUsername(id);
// other stuff..
}
async function getUsername(userid) {
try {
const result = await axios.post('/api/getuserdata' , {_id:userid});
const user = result.data;
}
catch (error) {
console.log(error)
}
}

Resources