Load data from function to state - reactjs

I have function which load all data from API. I would like to use that function to pass that data to array. But i cannot figured out how to do that.
I have already tried to put that function inside of state of my array, because I do not know how to use that function
function getRoles {
const url = 'URLTOENDPOINT'
fetchUtils.fetchJson(url, {
method: "GET",
})
.then(response => {
Object.keys(response.json.value).forEach(function (key) {
var object = response.json.value[key];
names.push(object.Name);
})
});
return names;
}
Simply i want to load data from getRoles function to this array inside state:
class MultipleSelect extends React.Component {
state = {
name: [
'Oliver Hansen',
'Van Henry',
'April Tucker'
]
};
...
Expected result should be MultipleSelect with default data loaded from API.
Any ideas how to use that function or what should be improved?

componentDidMount(){
this.setState({name:getRoles()})
}
you can try this way also function return directly set it to state variable
class MultipleSelect extends React.Component {
state = {
name: [
'Oliver Hansen',
'Van Henry',
'April Tucker'
]
};
getRoles() {
const url = 'URLTOENDPOINT'
var names
fetchUtils.fetchJson(url, {
method: "GET",
})
.then(response => response.json())
.then((res) => {
console.log(res)
names = res.value.map((data)=>(data.Name))
})
return names;
}
componentDidMount(){
this.setState({name:this.getRoles()})
}
}

Addition to my comment:
componentDidMount() {
fetch(
`https://xxx`,
)
.then(res => res.json())
.then(val=> {
this.setState({ ... });
});
}

Related

Using this.setstate with Fetch API

I'm trying to use a fetch call to retrieve some API data. Unfortunately I cannot use this to set the state.
consructor() {
this.state = {
weather: ""
};
this.search = this.search.bind(this);
}
search(postalCode) {
const url = `https://api.weatherbit.io/v2.0/forecast/daily?&postal_code=${postalCode}&key=${API_KEY}&days=7`;
fetch(url)
.then(response => response.json())
.then(data => console.log(data));
}'
This code works fine, and prints an object to the console containing the correct data.
consructor() {
this.state = {
weather: ""
};
this.search = this.search.bind(this);
}
search(postalCode) {
const url = `https://api.weatherbit.io/v2.0/forecast/daily?&postal_code=${postalCode}&key=${API_KEY}&days=7`;
fetch(url)
.then(response => response.json())
.then(data => this.setState({weather: data}))
.catch(error => console.log(error));
}
As soon as I try to use the data to update my state, I get the "this.setState is not a function" error. I've bound the search function in the constructor.
I've even tried to bind it like this:
fetch(url)
.then(response => response.json())
.then(data => this.setState({ weather: data })).bind(this);
This doesn't work either. Anyone have any ideas?
I can't see your class definition, but I believe that using the state requires you to extend Component
The issue you are getting is that this component doesn't have the state functions in it.
Here's some code from a working project of mine using similar fetches, returned by the services:
type HomeProps = {}
type State = {
projects: ProjectModel[],
skills: SkillModel[],
resume: JobModel[]
}
export default class Home extends Component<HomeProps, State> {
private projectService: ProjectService;
constructor(props: HomeProps) {
super(props);
this.projectService = new ProjectService();
this.state = {
projects: []
}
}
componentDidMount() {
this.getProjects();
}
private getProjects() {
this.projectService.retrieveItems().then(projects => {
this.setState({projects});
})
}
Here is the service:
export default class ProjectService {
url = "http://api.flynndev.us";
async retrieveItems() {
return fetch(`${this.url}/projects/all`)
.then(response => response.json());
}
async getItem(itemLink: string) {
return fetch(`${this.url}/projects/${itemLink}`)
.then(response => response.json());
}
}
Note: I'm using Typescript. Feel free to ignore the typing stuff for regular React

returning json from a separate file in react.js

trying to return json result to a component, trying to setup the json fetch in the separate file so i can reuse it. but stuggling
index.js
export const getData = (data) => {
return fetch('http://localhost:9968/api/vehicle')
.then(response => response.json())
.then((data) => {
return response.json()
})
carlist.js
import React, { Component } from 'react';
import { getData } from '../api';
export default
class CarList extends Component {
constructor(props) {
super(props);
this.state = {
data: null
}
}
componentDidMount() {
getData((data) => {
this.setState({
data
})
});
}
render() {
if(this.state.data) {
console.log(this.state.data);
return (
<h1>Car list</h1>
)
}
return (<h1>Loading...</h1>);
}
}
this is the json i expect to print to screen, in postman i know the end point works but react is not returning anything
{
"vehicles": [
{
"id": "x",
"modelYear": "98",
"url": "/api/vehicle/tt",
"media": [
{
"name": "vehicle",
"url": "/images/1.jpg"
}
]
},
{
"id": "z",
"modelYear": "99",
"url": "/api/vehicle/ff",
"media": [
{
"name": "vehicle",
"url": "/images/2.jpg"
}
]
},
]
}
This function you are using returns promise which should return json response.So remove the response.json() only return response from promise.
export const getData = () => {
return fetch('http://localhost:9968/api/vehicle')
.then(response => response.json())
.then((response) => {
return response
})
Then use async and await for componentDidMount and also remove the data that you are passing to getData function.
async componentDidMount() {
let response = await getData();
this.setState({
data: response
})
}
Your getData function returns promise.
In CarList component you can do this,
componentDidMount() {
getData(data).then((data) => {
this.setState({
data
})
});
}
Also your getData function is a bit wrong, you are returning response.json() instead of data, you should directly return data like,
export const getData = (data) => {
return fetch('http://localhost:9968/api/vehicle')
.then(response => response.json())
.then((data) => {
return data //instead of `response.json()` return data directly
})
}
Note: You are passing data to getData function but not using it, pass the data only when you need it.

How can i input an id into a axios request to pull specific data from backend

OK so kinda new here.
So currently I have data in the backend where I needed to pull it using a specific id so it gets the specific data for that user. In the backend, I just need to put it as an argument. In the front end, I'm able to pull the owner "ID" that I need to put in the argument I just don't know if I am doing it right here is my code for my front-end and server controller.also here is the pic of my logs 16 is the code for the specific user that i using enter image description here
class GetDogs extends Component {
constructor(props) {
super(props);
this.state = {
id: "",
dogs: []
};
}
async componentDidMount() {
//destructure get user function
const { getUser } = this.props;
//call function to get user info
await getUser();
//sets state into owner_id that i need to be put as the argument for my get dog's function
await this.setState({ id: this.props.userReducer.user.owner_id });
//call axios to bring dog info
await axios
.get(`/api/yourdogs`, {
owner_id: this.state.id
})
.then(response => {
this.setState({ dogs: response.data });
});
}
render() {
console.log(this.state.id);
console.log(this.state.dogs);
return <div>get dogs</div>;
}
}
const mapStateToProps = state => state;
export default connect(
mapStateToProps,
{ getUser }
)(GetDogs);
module.exports = {
newDog(req, res) {
const db = req.app.get("db");
const { name, age, picture, breed, sex, owner_id } = req.body;
db.newDog([name, age, picture, breed, sex, owner_id])
.then(response => {
res.status(200).send(response);
})
.catch(console.log);
},
getDogs(req, res) {
const db = req.app.get("db");
const { owner_id } = req.body;
db.getDogs([owner_id])
.then(response => res.status(200).json(response))
.catch(console.log);
}
};
instead of doing like this :
...
await this.setState({ id: this.props.userReducer.user.owner_id });
//call axios to bring dog info
await axios
.get(`/api/yourdogs`, {
owner_id: this.state.id // i don't think this.state.id is already assign new value
})
.then(response => {
this.setState({ dogs: response.data });
});
...
so, try it like this :
...
this.setState({ id: this.props.userReducer.user.owner_id }, () => {
//call axios to bring dog info
axios
.get(`/api/yourdogs`, {
owner_id: this.state.id
})
.then(response => {
this.setState({ dogs: response.data });
});
});
...

Setting state object dynamically using the data returned using Promise.all and fetch API : React+Typescript

I am using fetch API and promise.all for a scenario where I am passing an array of URL'S from where I am fetching the data. The data retrieved from all the above URL'S needs to be set to the state object.
Say I have an array of 5 URL's , the result returned by these must be
assigned to the 5 different values inside my state object.
Using React along with typescript.
Help would be appreciated.
This is what I have tried so far
import * as React from 'react';
const urls = [ 'http://localhost:3001/url1',
'http://localhost:3001/url2',
'http://localhost:3001/url3',
]
interface IState {
test: [],
result: [],
returnVal: []
}
export default class App extends React.Component<{},IState> {
constructor(props:any)
{
super(props);
this.state = {
test: [],
result: [],
returnVal: []
}
checkStatus(response:any) {
if (response.ok) {
return Promise.resolve(response);
} else {
return Promise.reject(new Error(response.statusText));
}
}
parseJSON(response:any) {
return response.json();
}
setData(data:any){
Object.entries(this.state).forEach(([key], index) => {
this.setState({ [key]: data[index] })
});
}
componentDidMount()
{
Promise.all(urls.map(url =>
fetch(url)
.then(this.checkStatus)
.then(this.parseJSON)
.catch(error => console.log('There was a problem!', error))
))
.then(data => {
this.setData(data);
})
}
render() {
return(
//some rendering code
)
}
}
Need to set the data returned from promise to the state object variables.
Promise.all(urls.map(url =>
fetch(url)
.then(this.checkStatus)
.then(this.parseJSON)
))
.then(jsons => {
var newState = {};
var index = 0;
for(var key in this.state)
newState[key] = jsons[index++];
this.setState(newState);
})

flux controller-view not subscribing for the event change in store

I want to show a list of messages when the page is loaded. i call action and addChangeListener to subscribe for changes in componentDidMount, hoping i can get the data back from server from store, though addChangeListener is called, but the callback is not being invoked. It seems like this.on('change', callback) in store is not working as it should. does anyone know what is the issue of my code? Im following the example on flux's repo
Also, where is the proper place to make api calls for backend data in store? is ok if i do it in getter in a store class?
thanks.
components/MessageList.js
class MessageList extends Component {
constructor(props) {
super(props)
this.renderMessage = this.renderMessage.bind(this)
this.state = {
loaded: false,
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
})
}
}
componentDidMount() {
messageActions.getAll()
messageStore.addChangeListener(this._onChange)
}
_onChange() {
console.log('on change') // <-- not being called from this point
this.setState({
dataSource: this.state.dataSource.cloneWithRows(messageStore.getAll())
})
}
//...
}
stores/MessageStore.js
let _messages = {}
function create(text, latitude, longitude) {
fetch('http://localhost:3000/api/message', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: text,
latitude: latitude,
longitude: longitude
})
})
.then(r => r.json())
.then(data => {
this.props.navigator.pop()
})
.done()
}
function getAllMessages(callback) {
fetch('http://localhost:3000/api/message')
.then((res) => res.json())
.then((data) => {
callback(data)
})
.done()
}
class MessageStore extends EventEmitter {
constructor() {
super()
}
emitChange() {
this.emit('change')
}
addChangeListener(callback) {
console.log('here') // <-- works
// this.on('change', callback) // <-- not working
this.on('change', () => console.log('helloooo')) // <-- not working
}
getAll() {
return _messages
}
}
dispatcher.register(action => {
switch(action.actionType) {
case 'MESSAGE_CREAT':
text = action.text.trim();
if (text !== '') {
create(text, action.latitude, action.longitude)
messageStore.emitChange()
}
break
case 'MESSAGE_ALL':
console.log('store..');
getAllMessages(data => _messages = data)
messageStore.emitChange()
}
})
const messageStore = new MessageStore()
export default messageStore
You cannot call the change listener in the store, you are only setting it up there. Try adding:
addChangeListener(callback) {
this.on('change', callback);
}
Instead of:
addChangeListener(callback) {
console.log('here') // <-- works
// this.on('change', callback) // <-- not working
this.on('change', () => console.log('helloooo')) // <-- not working
}
When a change happens, the changeListener in the store will trigger the change listener in MessageList:
messageStore.addChangeListener(this._onChange)
Then the _onChange function will be called.

Resources