React how can i replace the valeur of data - reactjs

as you can see on , i have two way to get the data.
The first one is localy, use the getdata() to read from local file.
function getData() {
const data = testData.map(item => {
return {
...item
};
});
return data;
}
The second one is a distance.
componentDidMount() {
fetch('https://XXXXX')
.then(res => res.json())
.then((data) => {
this.setState({ todos: data })
console.log(this.state.todos)
})
}
both work, but somehow i can not bind the second one to my app.
i am newbie on react technologie.

I think you can't define 2 state obj.
you have to delete one of them

Related

How to set state of other component inside an axios get method in react?

I'm using class-based components in react. I have few components named as follows: Blogs, BlogsClient, BlogCard. When Blogs mounts I make a call to a function inside BlogClient named as getBlogContent to fetch me data using axios.
setBlogs = (blogs) => {
this.setState({ "blogs": blogs });
}
componentDidMount() {
getBlogContent(this.setBlogs);
}
where getBlogContent is:
let getBlogContent = (setBlogs) => {
store.set('loaded', false);
axios.get(ADMIN_URL + '/getAllBlogs')
.then(response => {
store.set('loaded', true);
setBlogs(response.data.Response);
})
.catch(error => {
store.set('loaded', true);
store.set('errorMessage', error);
})
}
I'm able to fetch data and update my state properly. But If there comes any error inside Blogs or BlogCard(which is called inside Blogs) it goes inside the catch of getBlogContent whereas it should be only responsible for catching Axios error. What am I missing here?
Ok, so it's hard to tell without knowing these errors..
But nonetheless, you should avoid setting the component's state outside that component. So, your code'd become:
componentDidMount() {
const blogContent = getBlogContent();
if (blogContent !== 'error'j this.setBlogs(blogContent);
}
let getBlogContent = () => {
store.set('loaded', false);
return axios.get(ADMIN_URL + '/getAllBlogs')
.then(response => {
store.set('loaded', true);
return response.data.Response;
})
.catch(error => {
store.set('loaded', true);
store.set('errorMessage', error);
return 'error';
})
}

Issue with displaying data returned from REST API using React

I am trying out some stuff using the react-chatbot-kit in the front end and getting data from a REST API. Console.log shows the data inside .then, however I am getting the error "Uncaught TypeError: Cannot read property 'map' of undefined" when trying to output the data on the console inside the calling function. I need help to display the returned data in console.log in the function handleApiList(). Thanks in advance.
PS: I am a newbie of course in React :) since I am not clear on how to handle REST API calls that are done asynchronously. Look forward to getting this resolved. Any help and tips on resolving this will be greatly appreciated
Following is the code:
// ActionProvider starter code
class ActionProvider {
constructor(createChatBotMessage, setStateFunc) {
this.createChatBotMessage = createChatBotMessage;
this.setState = setStateFunc;
this.state = {
error: null,
users: []
}
}
greet() {
const greetingMessage = this.createChatBotMessage("Hi! Greeting!")
this.updateChatbotState(greetingMessage)
}
// This is being called when the user types in 'api' in chat window
handleApiList()
{
const { error, users } = this.state;
this.getData();
if(error) {
console.log("Error: ", error.message)
}
else {
let myarray=[]
users.map(function(user)
{
myarray += `${ user.name }\n`;
return `${ user.name }`;
})
console.log(myarray)
}
}
getData()
{
console.log("in now")
fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
.then(
(result) => {
this.setState({
users: result
});
},
(error) => {
this.setState({ error });
}
)
}
handleJobList = () => {
const message = this.createChatBotMessage(
"Fantastic, I've got the following jobs available for you",
{
widget: "jobLinks",
}
);
this.updateChatbotState(message);
};
updateChatbotState(message) {
// NOTE: This function is set in the constructor, and is passed in
// from the top level Chatbot component. The setState function here
// actually manipulates the top level state of the Chatbot, so it's
// important that we make sure that we preserve the previous state.
this.setState(prevState => ({
...prevState, messages: [...prevState.messages, message]
}))
}
}
export default ActionProvider;
You are fetching in getData and it's an async function. The data is not ready. It's better to just return the data than to setting state.
simplified version of your code.
handleApiList()
{
const { error, users } = this.state;
const data = await this.getData();
//data is ready, do what u want with the data here.
}
}
const getData = async() => {
return fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
)
}
.map returns an array, if you want to push u need to use forEach.
Example
let myarray=[]
data.forEach((user) =>
{
myarray.push(user.name });
})
console.log(myarray)
Issue description:
const { error, users } = this.state; // gets state values
this.getData(); // updates state values
if(error) {
console.log("Error: ", error.message)
}
else {
let myarray=[]
users.map(function(user) // users is value before state update
I would suggest returning from getData() a promise with result of api call. After that you can execute code in handleApiList() in .then().
Proposal:
getData()
{
console.log("in now")
return fetch("https://jsonplaceholder.typicode.com/users")
.then(res => res.json())
.then(
(result) => {
this.setState({
users: result
});
return result;
}
)
}
I would also move error handling to .catch().
Also have a look on this. Working using async/await instead of pure Promises is easier and cleaner ;)

Forming an array from two joined apis in react

I am attempting to create a set of joined data from two apis that I would love to implement in a table, apparently I am not getting the expected result.
The logic behind my code is :
Get the data from the first api
loop through each element in the data to get a specific data from the second api depending with the id of each element.
Create a new key to each element, each data obtained in second api as a value.
the resulting data is set in the state.
I have been able to accomplish step 1 to 3 except step 4.
class App extends React.Component{
constructor(props){
super(props);
this.state = {
Data: [],
};
}
componentDidMount() {
fetch('http://localhost:8000/tasks?format=json')
. then(res => res.json())
.then(data => data['results'].forEach(element => {
fetch(`http://localhost:8000/task/${element.id}/runs`)
.then(res => res.json())
.then(data2 => element['rundata'] = data2)
.then(this.state.Data.push(element))
}))
.catch(err => console.log(err))
}
render(){
console.log('data', this.state.Data)
return(
)
}
}
export default App;
You can only update react state with setState method.
Try the below code.
then(this.setState(prev => ({
data: [...prev, element]
})
Well the main reason for the issue is that you are not using setState correctly.
you need to use setState, and you need to not mutate the state. Always copy the old state and then modify it.
The second issue which may occur is that your forEach method is not synchronised.
Try changing your componentDidMount to this:
componentDidMount() {
fetch('http://localhost:8000/tasks?format=json')
.then(res => res.json())
.then(data => {
for (const element of data['results']) {
fetch(`http://localhost:8000/task/${element.id}/runs`)
.then(res => res.json())
.then(data2 => element['rundata'] = data2)
.then(this.setState({ Data: [...Data, element] })
}
}
.catch(err => console.log(err))
}
this.setState(prevState => ({
myArray: [...prevState.myArray, "new value"]
}))
in the other hand, i don't recommend to loop in fetch, either you use a post method and loop throw all the ids in your server side and return an array, or if you have a light database you get all the result and do a loop in your client side.
When you're setting data into the state in React you only need to use this.setState().
So for your case you only have to run this.setState({ Data: element }).
Maybe this :
componentDidMount() {
fetch('http://localhost:8000/tasks?format=json')
.then(res => res.json())
// create array of promise
.then(data => data.results.map(element => {
return fetch(`http://localhost:8000/task/${element.id}/runs`)
.then(res => element.rundata = res.json())
.cath(err => console.log(err))
}))
.then((arrayPromise) => {
Promise.all(arrayPromise)
.then(resolved => this.setState({data:resolved}))
})
.catch(err => console.log(err))
}
render(){
console.log('data', this.state.data)
return(
<></>
)
}
}

React componentDidMount not setting states before page loads

Working on a MERN application, I have a componentDidMount that uses axios to retrieve from the backend some Ids and retrieve product info(prods) from the ids. However the states in my application are still empty when the page is loaded initially, instead I'll have to make a change to state before the states are set.
I believe it might have something to do with having an array mapping in the componenDidMount, I could change the backend so in node. However i would like to see if anything could be done in the frontend first.
componentDidMount() {
axios
.get("/api/featureds")
.then(response => {
this.setState({
featureIds: response.data
});
response.data.map(({ prodId, _id }) =>
axios
.get("/api/prods/" + prodId)
.then(response => {
if (response.data == null) {
} else {
this.state.featureTempList.push(response.data);
}
})
.catch(error => {
console.log(error);
})
);
this.setState({
featureProds: this.state.featureTempList
});
})
.catch(error => {
console.log(error);
});
}
Why are you trying to set state like this?
this.state.featureTempList.push(response.data)
State should be set by this.setState().
So you can try doing this:
this.setState((oldState) => ({
featureTempList: oldState.featureTempList.push(response.data)
});
Just remember to set featureTempList to state when you initialize:
state = {
featureTempList: []
}

Cannot fetch api due to array react native

I bulid an api using laravel which can run in postman (http://lkcfesnotification.000webhostapp.com/api/notifications). The problem is when i fetch using an example from this (https://www.youtube.com/watch?v=IuYo009yc8w&t=430s) where there is a array in the api then i have to setstate the array which is working well but when i try using the below code it does not render due to it is not using array in the api for example the random user api have "results" :[item], and mine one is "data":[my item]
fetchData = async () => {
const response = await fetch("https://randomuser.me/api?results=500");
const json = await response.json();
this.setState({ data: json.results });
};
if i use this will work but i want to use below code due to some homework i am doing
type Props = {};
export default class IndexScreen extends Component<Props> {
...
this.state = {
data: [],
isFetching: false,
};
_load() {
let url = "http://lkcfesnotification.000webhostapp.com/api/notifications";
this.setState({isFetching: true});
fetch(url)
.then((response) => {
if(!response.ok) {
Alert.alert('Error', response.status.toString());
throw Error('Error ' + response.status);
}
return response.json()
})
.then((members) => {
this.setState({data});
this.setState({isFetching: false});
})
.catch((error) => {
console.log(error)
});
}
https://imgur.com/a/he5mNXv this is my render
the result i get the code i run is blank is loading
The fetch request is working but you are not saving the right data in the right state property.
The issues is located in the following part:
.then((members) => {
this.setState({data});
this.setState({isFetching: false});
})
You are assigning the response to a variable members but saving another variable data, which does not exist.
In addition, the response is an object with more information than just the data, so what you are looking for is just the data property of the response.
This should work:
.then(({ data }) => {
this.setState({data});
this.setState({isFetching: false});
})
Here we destructure the response into the variable { data }, solving your issue.
Based on the snippets you don't use the fetched data to set it to your state:
.then((members) => {
this.setState({data});
this.setState({isFetching: false});
})
membersis the result of your fetched json. So either rename members to data or use data: members. If the code should work like your first function it's probably data: members.result. You can also combine the two setState calls to one single call:
this.setState({
data: members.result,
isFetching: false,
});

Resources