Setting State with a parameter - javascript

Not sure what i'm tyring to do is possible, but
state = {
characters: [],
planets: [],
search: "",
selectedCharacter: null
};
componentDidMount() {
this.fetchSomeData(
"https://rickandmortyapi.com/api/character/",
"characters"
);
this.fetchSomeData("https://rickandmortyapi.com/api/location", "planets");
}
fetchSomeData = (url, stateToSet) => {
fetch(url)
.then(res => res.json())
.then(data => this.setState({
[stateToSet]: data.results,
next: data.info.next,
prev: data.info.prev
}))
.catch(err => alert(err));
};
I have a characters page, and a planets page both obviously 2 different endpoints from the api
https://rickandmortyapi.com/api/character/
https://rickandmortyapi.com/api/location/
the problem i'm having:
when
componentDidMount(){
}
runs it's fetching both sets of data, then storing both
next page endpoints in the next state
"https://rickandmortyapi.com/api/location/?page=2"
"https://rickandmortyapi.com/api/character/?page=2",
i need to access next when clicking a button to reload the next page of data. (one component displays characters, for that one i need the "https://rickandmortyapi.com/api/character/?page=2",
and one component displays planets for that one i need "https://rickandmortyapi.com/api/character/?page=2",
)
how can i store these 2 separately?
i was thinking of trying to match them to their respective endpoints like this:
fetchSomeData = (url, stateToSet) => {
fetch(url)
.then(res => res.json())
.then(data => this.setState({
[stateToSet]: data.results,
**[stateToSet]next: data.info.next,**
prev: data.info.prev
}))
.catch(err => alert(err));
};
but i'm not sure you can incorporate the parameter into it like that.

You need to change a small thing in fetchSomeData like below:
fetchSomeData = (url, stateToSet) => {
fetch(url)
.then(res => res.json())
.then(data => this.setState({
[stateToSet]: data.results,
[`${stateToSet}-next`]: data.info.next,
[`${stateToSet}-prev`]: data.info.prev
}))
.catch(err => alert(err));
};
used [${stateToSet}-next] Template literals. Hope it helps and demo
This will print :
{
characters: Array[20],
characters-next: "https://rickandmortyapi.com/api/character/?page=2"
characters-prev: ""
planets: Array[20],
planets-next: "https://rickandmortyapi.com/api/location?page=2"
planets-prev: ""
search: "",
selectedCharacter: ""
}
and #Croolsby's answer also nice solution.

This should do it:
fetchSomeData = (url, stateToSet) => {
fetch(url)
.then(res => res.json())
.then(data => this.setState({
[stateToSet]: {
results: data.results,
next: data.info.next,
prev: data.info.prev
}
}))
.catch(err => alert(err));
};
Then you can access it like this:
this.state.characters.next
this.state.planets.next
The general lesson here is that you can have nested objects inside this.state.

Related

Save API data into an array with vue.js

I need help doing this. I want to save the user list from the API to an array (called "name"). How can I do this? I tried this forEach but can't make it work. Thanks!
Edit: I wraped the function, still not working.
import axios from 'axios'
export default {
data () {
return {
info: null,
name: []
}
},
mounted () {
axios
.get('http://localhost:3000/api/users/', {mode: 'no-cors'})
.then(response => (this.info = response.data))
.then(() => info.data.forEach(element => {
}))
.catch(error => {
console.log(error)
this.errored = true
})
.finally(this.loading = false)
}
}
From the code above I'm assuming the data in this.info in correct. The problems I see in your code are:
1.
.then(response => (this.info = response.data))
.then(() => info.data.forEach(element => {
}))
info looks to be undefined. I assume this should be this.info.
.then(response => (this.info = response.data))
.then(() => this.info.data.forEach(element => {
}))
Or if you're using the arrow function syntax and returning an assignment expression, you can use
.then(response => (this.info = response.data))
.then(info => info.data.forEach(element => {
}))
Which I don't really recommend, since some linting rules disallow returning assignment expressions (for good reasons). To chain a promise that relies on this implicit language behavior can make code less easily understood.
2.
What forEach does matters. Vue's reactivity does not pick up certain assignment syntax, i.e. this.name[i] = element. You can use array methods like push, but I recommend you use functional programming operators, like map and filter:
.then(() => (this.name = this.info.data.map(element => {
})))
Maybe the this reference is not correct, because on callback methods is on another context, try it:
export default {
data () {
return {
info: null,
name: []
}
},
mounted () {
var self = this
axios
.get('http://localhost:3000/api/users/', {mode: 'no-cors'})
.then(response => (self.info = response.data))
.then(info.data.forEach(element => {
});)
.catch(error => {
console.log(error)
this.errored = true
})
.finally(this.loading = false)
}
}
you forgot to encapsulate the callback into a function receiving the info variable,
try this:
import axios from 'axios'
export default {
data () {
return {
info: null,
name: []
}
},
mounted () {
axios
.get('http://localhost:3000/api/users/', {mode: 'no-cors'})
.then((response) => response.data.forEach(element => {
}))
.catch(error => {
console.log(error)
this.errored = true
})
.finally(this.loading = false)
}
}

How to fetch data from multiple db from the node.js in frontend react.js

I have the below code, where I have to get data from all the files in the same DB. Node.js is running at the backend. When I try the below code, I always get the last fetch, can anyone please help me how to fix this.
The below is from the react JS frontend.
componentDidMount() {
console.log("This Worked Sucessfully")
this.getDataFromDb();
if (!this.state.intervalIsSet) {
let interval = setInterval(this.getDataFromDb, 1000);
this.setState({ intervalIsSet: interval });
}
}
getDataFromDb = () => {fetch('http://172.24.78.202:3001/api/passed')
.then(data => data.json())
.then(res => this.setState({ passed: res.data }));
};
getDataFromDb = () => {fetch('http://172.24.78.202:3001/api/failed')
.then(data => data.json())
.then(res => this.setState({ failed: res.data }));
};
getDataFromDb = () => {fetch('http://172.24.78.202:3001/api/all')
.then(data => data.json())
.then(res => this.setState({ data2: res.data }));
};
render() {
const primaryColor = getColor('primary');
const secondaryColor = getColor('secondary');
const { passed, failed, data2 } = this.state
From what I see by your code, you seem to be re-writing your goGetDataFromDB two times. Try changing the names of each function or, the way you call them. You can also take advantage of Promise.all to group the results of each call into a single return handle.
Check this link for the documentation of Promise.all
You could refactor your current code to something like this:
class MyComponent extends React.Component {
componentDidMount() {
this.getDataFromDb();
if (!this.state.intervalIsSet) {
let interval = setInterval(this.getDataFromDb, 1000)
this.setState({intervalIsSet: true })
}
}
getDataFromDb = () => {
Promise.all([
'http://172.24.78.202:3001/api/passed',
'http://172.24.78.202:3001/api/failed',
'http://172.24.78.202:3001/api/all'
].map(url => (
fetch(url)
.then(data => data.json())
.then(res => res.data)
)
)).then(([passed, failed, data2]) =>
this.setState({ passed, failed, data2 })
);
}
render() {
//...
}
}
I tried to keep as much as your code as possible so you could notice the differences.
I hope this helps.

receiving data from api but cant setState

For some reason, I am unable to update the state of my component with the data from my fetch request.
When I console.log, I can see that I am getting the data. I'm not sure what this could be
If this is a noob issue, please bear with me. I'm still learning.
Here is my code:
import React, { Component } from "react";
class Nav extends Component {
state = {
searchTerm: "",
posts: []
};
getPost = e => {
e.preventDefault();
const val = e.target.value;
this.setState({ searchTerm: val }, () => {
if (val !== "") {
fetch(
`http://www.reddit.com/search.json?q=${val}&sort=relevance&limit=25`
)
.then(res => res.json())
.then(data => console.log(data.data))
//.then(data => this.setState({ posts: data.data }))
//.then(console.log(this.state.posts))
.catch(err => console.log(err));
}
});
};
Actually everything is right and going well, just your logging is wrong.
.then(console.log(this.state.posts))
That logs the state now and passes the result of console.log() (undefined) to the .then chain as a callback which is obviously wrong. I guess you meant:
.then(() => console.log(this.state.posts))
But that still won't work as setState does not trigger a state update immeadiately, but somewhen. After that it calls the second argument as a callback, so you should log then:
.then(data => this.setState({ posts: data.data }, () => {
console.log(this.state.posts);
}))
Altogether:
const response = fetch(
`http://www.reddit.com/search.json?q=${val}&sort=relevance&limit=25`
).then(res => res.json());
// PS: I would not build up a chain if the logic is not really "chained"
response.then(data => console.log(data.data));
response.then(data => this.setState({ posts: data.data }, () => console.log(this.state.data)));
response.catch(err => console.log(err));

Event to check all flux events are loaded in current page - Flux, React

I need to trigger an event, to check if all the event loading are complete in the current page / current route.
For suppose
Current route is `/address`
The events which are loaded in this routes are
LOAD_NAME
LOAD_PHONE_NUMBER
LOAD_GOOGLE_LOCATION
So here LOAD_GOOGLE_LOCATION will take its time to execute. I need to trigger another Event after all these event loading are complete
I'm using React and Flux
If you are using redux-thunk, you can implement your actions like that:
const loadName = url => dispatch => fetch(url)
.then(res => res.json())
.then(json => {
dispatch({ type: 'LOAD_NAME', data: json }
return json;
}))
const loadPhoneNumber = url => dispatch => fetch(url)
.then(res => res.json())
.then(json => {
dispatch({ type: 'LOAD_PHONE_NUMBER', data: json };
return json;
}))
const loadGoggleLocation = url => dispatch => fetch(url)
.then(res => res.json())
.then(json => {
dispatch({ type: 'LOAD_GOOGLE_LOCATION', data: json };
return json;
}))
//load one after the other
const loadAll = () => dispatch =>
loadName(…)
.then(json => loadPhoneNumber(json.number))
.then(json => loadGoogleLocation(json.location))
.then(dispatch({ type: 'ALL_LOAD' }))
//load all in parallel
const loadAll = () => dispatch => Promise.all([
loadName(…),
loadPhoneNumber(…),
loadGoggleLocation(…)
])
.then(([namejson, numberjson, locationjson]) =>
dispatch({ type: 'ALL_LOAD' }))
This way:
your actions can still be used »standalone«
your state gets updated as data arrives,
you do not need to check the state for existing data/flags to make sure all dependencies are met
you can easily extend this to much more dependencies

Using variables in multiple functions - react native

I'm looking to fetch some data then use it to fetch some other data, the first api returns a some news articles, I'm doing a for loop to access descriptions and save it as an array, I want then to use that array to make another fetch request, the issue is that I'm only able to access arrayin the first function, my code looks like that:
makeRemoteRequest = () => {
const url = `https://url.com`;
fetch(url)
.then(res => res.json())
.then(res => {
maindata = res.articles
var array = []
for(let i in maindata){
array.push(maindata[i].description)
}
console.log(array) // Working
this.setState({
data: res.articles,
});
})
console.log(array) // Not working
console.log(this.state.data) // Not working
};
I'm able to use this.state.data in component and render it on a listview.
Second function:
fetch('url', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
'api_key': "81a354b",
'data': array
}),
})
My last attempt was to mix everything in a single function since it's all promises, didn't work
fetch(url)
.then(res => res.json())
.then(res => return res.articles.map(article => article.description) )
.then(res => fetch(otherUrl, { descriptions: res }))
.then(res => {
})
Just define the variable outside of the fetch scope first.
let array = [];
Then inside the fetch:
array.push()
What is the output of this? (could you please add the output formatted in your question?):
fetch(url)
.then(res => res.json())
.then(res => return res.articles.map(article => article.description) )
.then(res => fetch(otherUrl, { descriptions: res }))
//I assume that result needs to be parsed as json as well
.then(res => res.json())
.then(result => {
conole.log("got results:",results);
})
.catch(err =>
console.warn("something went wrong:",err);
)

Categories