Reputation: 69
I am new to javascript and reactJS and I'm stuck. I have a javascript file where I make a REST call. The file looks like this:
var data;
function getDataRequest() {
const request = new XMLHttpRequest();
request.open('GET', "localhost:8080/getData", true);
request.onload = function () {
var data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
products = data;
} else {
console.log('error');
}
};
request.send();
}
var getDataList = function() {
getDataRequest();
return data;
};
getDataList();
And the file which contains the React component looks like this:
var = data;
class Datas extends React.Component {
render() {
data = this.getDataList;
return (
<DataTable data={data} />
);
}
}
export default Products;
The problem is that data in the React component remains 'undefined'. I am making the rest call in a different file because I want to call the rest call from multiple react components.
Upvotes: 3
Views: 17172
Reputation: 79
Firstly, there are no function getDataList
in your React Component Datas
.
Secondly, if you want to call getDataList
from your React Componet, please export or make your function is global. You can use:
window.getDataList = function() {
getDataRequest();
return data;
};
and in your React Component, you can call window.getDataList()
easily.
Upvotes: 1
Reputation: 4008
You need to pass a callback to your generic function to be able to update the state
function getDataRequest(callback) { // here
const request = new XMLHttpRequest();
request.open('GET', "localhost:8080/getData", true);
request.onload = function () {
var data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
callback(data) // here
} else {
console.log('error');
}
};
request.send();
}
You need to create a state and trigger the call in the componentDidMount, after the first render.
export default class Datas extends React.Component {
state = {
data: null // or [] ?
}
componentDidMount(){
const callback = (value) => {
this.setState({
data: value
})
}
this.getDataList(callback);
}
render() {
const {
data
} = this.state;
return (
<DataTable data={data} />
);
}
}
Upvotes: 0
Reputation: 41
You need to be aware of the React component lifecycle. In a nutshell, there are certain functions that React calls in a certain order. Some are called before the component is rendered and some are called after. In your case, you want to make an API call once the component is rendered. An appropriate lifecycle method for this is componentDidMount. Please see here for more detailed information about the component lifecycle methods.
Below is an example of this behaviour. Note that I have used the fetch API instead of XmlHttpRequest. It is much cleaner to work with and is part of JavaScript.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false,
something: ""
};
}
componentDidMount() {
fetch("exampleurl")
.then(response => {
return response.json();
})
.then(json => {
// perform desired checks etc
this.setState({
something: json.someProperty
});
});
}
render() {
if (!this.state.loaded) {
return <div>{"Loading..."}</div>;
}
return <div>{this.state.something}</div>;
}
}
export default Example;
Upvotes: 1
Reputation:
You're grabbing data from the server in your render call, which is a really bad idea.
Use componentDidMount
to load data, then store it in the state.
First, here's you Data.js
:
export default {
getDataList: () => fetch("//localhost:8080/getData").then(res => res.json())
};
In your Component, import Data from './Data';
, then do this:
componentDidMount = () => { // using this syntax auto-binds 'this'
Data.getDataList().then(res => {
this.setState({ data: res });
});
}
render() {
return (
<DataTable data={this.state.data} />
);
}
Upvotes: 4