Using a POST request's response values in React Native - reactjs

everyone. I'm a new developer and this is my first post here, so please bear with me.
What I'm trying to do is access the values that I received from a POST request that I made.
Below you can see what I'm trying to do. I set up a state where I'll store my data and then there's a function called fetchData that does a POST request and receives an object with the values, right?
Now I that I've received my object, I want to store its values in some of my variables.
Since the values have been stored in the 'data' state, I thought I would access its values by doing something like 'userName = data.userName', or something like 'age = data.userAge'. Obviously that didn't work out because my IDE does not know those values yet lol. So how do you think I should access them?
const [data, setData] = useState([{}]);
useEffect(() => {
fetchData({
ids: [0],
})
.then((response: any) => {
setData(response);
})
.catch((error: any) => {
console.log('error', error);
});
}, []);

dont place the function directly in useEffect, do something like this instead
const [data, setData] = useState([])
const getData = async() => {
try{
const response = await fetchData({ids: [0]});
setData(response);
}catch(error){
console.log(error);
}
}
useEffect(() => {
getData();
},[])

Related

React cannot setState in useEffect

const [soilInfo, setSoilInfo] = useState([]);
const [ambient, setAmbient] = useState([])
useEffect(() => {
const getSoil = () => {
axios.get("http://localhost:8081/soil_info").then((response) => {
setSoilInfo(response.data);
console.log(response.data);
})
}
getSoil();
console.log(soilInfo);
},[])
useEffect(() => {
const getAmbient = () => {
axios.get("http://localhost:8081/ambient").then((response) => {
setAmbient(response.data);
console.log(response.data);
})
}
getAmbient();
console.log(ambient);
}, [])
I tried debugging by printing in get function and after get function. It turns out that soilInfo and ambient are null sets. The response was fine. This is the results
I have a couple of ideas here:
Your axios get call could be failing. This would result in your then clause not being called. I would try logging out the response or adding a catch clause to verify the request is working.
Both setSoilInfo and setAmbient are expecting a list at the moment (if you are using Typescript at least). What data type is response.data? If you know, I'd recommend typing your useState like so: useState<TYPE[]>. Then you can get some type help.
Let me know if you have questions about either of the above.

How to assign data to a variable from axios get() response

I am trying to use Express (axios) to build a React app.
I was able to get an array of objects from MongoDB using get() method. Currently the list is printed out to the console. How can I assign it to a variable so that I could use that array for further actions?
useEffect(() => {
const expensesListResp = async () => {
await axios.get('http://localhost:4000/app/expenseslist')
.then(
response => console.log(response.data))
}
expensesListResp();
}, []);
Many thanks!
You can assign it in the following way, let say you have an array posts:
const [posts, setPosts] = useState([]);
useEffect(() => {
axios.get('url')
.then(res => setPosts(res.data))
.catch(err => console.log(err));
}, [])
In your code, you can do it in this way:
const [resultArray, setResultArray] = useState([]);
useEffect(() => {
const expensesListResp = async () => {
await axios.get('http://localhost:4000/app/expenseslist')
.then(
response => setResultArray(response.data))
}
expensesListResp();
}, []);
I am assuming that you have data printed on the console.log(response.data) and you want it to be assigned to a variable so that you can use it right?
if that's the case you are already using async function just name it with whatever variable name you want it to be before await.
for example:
const expensesListResp = async () => {
const "your variable name" = await axios.get('http://localhost:4000/app/expenseslist')
}
you can also save that variable in your state, if you want to use that variable data throughout your application.

useEffect not triggering but the template is being rendered somehow

I am getting too many re-renders while using react-hooks.
I am trying to fetch data from api by using a parameter in URL.
Here's the code:
export default function Details() {
const { title } = useParams();
const [loading, setLoading] = useState(true);
const [details, setDetails] = useState([]);
const [error, setError] = useState("");
function getDetails(keyword) {
if (keyword) {
setLoading(true);
fetch(
`API`
)
.then((res) => {
let result = res.data.results;
result = result.filter(function (result) {
return (result.title = keyword);
});
setDetails(result[0]);
setLoading(false);
console.log(details);
})
.catch((err) => {
setError(["Unable to fetch data"]);
setLoading(false);
});
}
}
getDetails(title)
return(
// template
)
now I think this is happening at the line where I call getDetails.
then I tried using useEffect to load the data only once after it is mounted,
useEffect(() => {
getDetails(title);
}, []);
It still is unable to fetch the data, as the getDetails function is never called.
How can I resolve this?
Edit:
Fixed one silly error.
Here's the codesandbox link:
Codesandbox
There are multiple issues with this, first you need to specify what you want to be notified about when the useEffect gets called again. You could do this by adding the variables you want within the array
useEffect(() => {
getDetails(title);
}, [
// Add what you want here
]);
The second issue you have is that you declared the detalis variable twice. Once using the set state here: const [details, setDetails] = useState([]);
The second time here:
const details = getDetails(title)
the code here has two obvious error beside the functionality problems you mentioned:
1 - you cannot declare two variables with same name using let or const; it will throw a SyntaxError
const [details, setDetails] = useState([]);
...
const details = getDetails(title)
2- getDetails function is written with a asynchronous mindset, and it will return nothing,
so details in const details = getDetails(title) will be set to undefined
Looks like your getDetails function has title param so I would add title and getDetails both in the dependency list of useEffects
Or place getDetails inside the useEffect
Here is your working code. You had multiple problems where res.data was undefined so you need to get res.results directly based on your response object
useEffect(() => {
function getDetails(keyword) {
if (keyword) {
setLoading(true);
fetch(
`https://api.jikan.moe/v3/search/anime?q=${keyword}&page=1&genre_exclude=0`
)
.then((res) => res.json())
.then((res) => {
console.log(res.results);
let result = res.results;
console.log(result);
result = result.filter(function (result) {
return (result.title = keyword);
});
setDetails(result[0]);
setLoading(false);
console.log(3);
})
.catch((err) => {
console.log(err);
setError(["Unable to fetch data"]);
setLoading(false);
});
}
}
console.log('calling getDetails')
getDetails(title);
}, [title]);
Note: tested in the code sandbox link provided in the question. Its working code.

How to update state array fetched from API in React Hooks?

I'm fetching data from Studio Ghibli API and I am able to successfully fetch it, set the state array of objects and render it in my presentational component. However, I'm trying to create a function which will add new property "keyword" to every object in my state array. The problem is that when i try to copy the state array to manipulate it in my createKeywords function, the returned copy is empty and I'm unable to manipulate it after it being set.
This is the relevant code:
const baseUrl = 'https://ghibliapi.herokuapp.com/'
const [hasError, setErrors] = useState(false)
const [movies, setMovies] = useState([])
useEffect(() => {
fetch(baseUrl + 'films')
.then((res) => res.json())
.then((res) => {
console.log(res);
setMovies(res)
createKeywords()
})
.catch(err => setErrors(true));
}, [])
const createKeywords = () => {
const moviesWithKeywords = [...movies]
moviesWithKeywords.forEach(function(movie){
movie.keyword = 'castle'
});
setMovies(moviesWithKeywords)
}
If i don't call the createKeywords function everything works fine but obviously copying and setting new movies state creates problem. I tried adding [movies] instead of empty array in useEffect and that works but then useEffect runs indefinitely. Thank you in advance, React isn't my strong suit!
The solution seems might not be very obvious. There are cases where setMovies (in general setting the state) is an async operation, which means that even if you setMovies the movies variable is not being updated quite fast and therefore you are already executing the createKeawords function. This means that within the keywords function the movies variable didn't have the chance to update fast enough. I would recommend to pass the res as a parameter in the createKeywords and use this variable to copy the array to the moviesWithKeywords.
Have a look here under the section State Updates May Be Asynchronous
So do something like that:
const baseUrl = 'https://ghibliapi.herokuapp.com/'
const [hasError, setErrors] = useState(false)
const [movies, setMovies] = useState([])
useEffect(() => {
fetch(baseUrl + 'films')
.then((res) => res.json())
.then((res) => {
console.log(res);
setMovies(res)
createKeywords(res)
})
.catch(err => setErrors(true));
}, [])
const createKeywords = (movies) => {
const moviesWithKeywords = [...movies]
moviesWithKeywords.forEach(function(movie){
movie.keyword = 'castle'
});
setMovies(moviesWithKeywords)
}

React setState to push all items in array to state

so I am trying to load all chat messages on page load. The messages are being retrieved just as I want them but I am having a horrible time trying to push all of them to state, I tried using loops etc but nothing seemed to work. This is the code:
const [name, setName] = useState("")
const [room, setRoom] = useState("")
const [messages, setMessages] = useState([])
const { room, name } = queryString.parse(location.search)
loadMessages(room).then((response) => {
if (response.error) {
console.log(response.error)
} else {
console.log(response)
setMessages([
...messages,
{ text: response.message, user: response.sender },
])
}
})
I just want to push every object in the response array into the messages state. Help greatly appreciated!
You need to use the useEfect hook for data fetching.
The Effect Hook lets you perform side effects in function components
Data fetching, setting up a subscription, and manually changing the
DOM in React components are all examples of side effects. Whether or
not you’re used to calling these operations “side effects” (or just
“effects”), you’ve likely performed them in your components before.
https://reactjs.org/docs/hooks-effect.html
From your snippet, it would look something like this:
useEffect(() => {
const messages = async () =>
await loadMessages(room)
.then(response => {
if(response.error) {
console.log(response.error)
} else {
console.log(response)
setMessages([...messages,
{text: response.message,
user: response.sender}
]);
}
});
messages();
}, []);
if the response is an array of messages, then you should map it and then set the state to it, like:
setMessages(response.map(item => ({
text: item.message,
user: item.sender
})
));
Ps: also as #George answered, also you should put the setMessages on a useEffect(() => {}, []) to prevent it to get datas on every update.

Resources