I'm trying to get XML-Data from an XML-file and want to save certain node values in a list. This is how I tried to do it:
import React from "react";
class EditFiles extends React.Component {
constructor(props) {
super(props);
this.loadXML = this.loadXML.bind(this);
}
loadXML = () => {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var xmlDoc = this.responseXML;
var y = xmlDoc.getElementsByTagName("newFile");
for(var i=0; i<y.length; i++) {
var NameArray = [y[i].getElementsByTagName("FileName")[0]];
}
const nameList = NameArray.map(name =>
<li>{name}</li>
);
}
};
xhttp.open("GET", "./FilenameList.xml", true);
xhttp.send();
}
render() {
return(
<ul>{nameList}</ul>
);
}
}
First of all, I don't know if it can even be done this way. I did find similar questions, however, the code in the answers was not explained very well and I don't want to just copy and paste some code without understanding it (also, even if I wanted to do that, I probably couldn't, since I wouldn't know what represents what.
The error I'm getting with this code is that nameList
is not defined in the render function. I know that it would have to be a global function, but I do not know how to do that.
I also read this post: /@catquarks/making-ajax-requests-with-react-48be0285d396 and wanted to do it like in the example. But I don't quite understand it, for example, how would I get the value of certain tags?
Anyway, to sum up my goal for this question: Can I use an XMLHttpRequest the way I did and what mistakes did I make exactly?
I hope this isn't all over the place. If you need further information/explanation please let me know.
Quick Edit: the XML-file looks kinda like this:
<Files>
<newFile>
<FileName>file1</FileName>
</newFile>
<newFile>
<FileName>file2</FileName>
</newFile>
</Files>
What I would also like to note, is that the xml-file is created dynamically, therefore it's not predictable how many newFile
nodes there are going to be.
I'm trying to get XML-Data from an XML-file and want to save certain node values in a list. This is how I tried to do it:
import React from "react";
class EditFiles extends React.Component {
constructor(props) {
super(props);
this.loadXML = this.loadXML.bind(this);
}
loadXML = () => {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var xmlDoc = this.responseXML;
var y = xmlDoc.getElementsByTagName("newFile");
for(var i=0; i<y.length; i++) {
var NameArray = [y[i].getElementsByTagName("FileName")[0]];
}
const nameList = NameArray.map(name =>
<li>{name}</li>
);
}
};
xhttp.open("GET", "./FilenameList.xml", true);
xhttp.send();
}
render() {
return(
<ul>{nameList}</ul>
);
}
}
First of all, I don't know if it can even be done this way. I did find similar questions, however, the code in the answers was not explained very well and I don't want to just copy and paste some code without understanding it (also, even if I wanted to do that, I probably couldn't, since I wouldn't know what represents what.
The error I'm getting with this code is that nameList
is not defined in the render function. I know that it would have to be a global function, but I do not know how to do that.
I also read this post: https://medium./@catquarks/making-ajax-requests-with-react-48be0285d396 and wanted to do it like in the example. But I don't quite understand it, for example, how would I get the value of certain tags?
Anyway, to sum up my goal for this question: Can I use an XMLHttpRequest the way I did and what mistakes did I make exactly?
I hope this isn't all over the place. If you need further information/explanation please let me know.
Quick Edit: the XML-file looks kinda like this:
<Files>
<newFile>
<FileName>file1</FileName>
</newFile>
<newFile>
<FileName>file2</FileName>
</newFile>
</Files>
What I would also like to note, is that the xml-file is created dynamically, therefore it's not predictable how many newFile
nodes there are going to be.
1 Answer
Reset to default 3You need to tell React how and when to execute the code in your loadXML
function. Binding it like you did in the constructor is useless here, as bind
simply changes the this
keyword for the loadXML
function. And actually, React es with a set of functions you should use instead, as loadXML
's purpose is to fetch data from an external source.
In your case, ponentDidMount
is the right place to execute the code instructions of loadXML
.
A best practice is to :
- set your initial
state
in thecontructor()
function - load external data (what you do with
XMLHttpRequest
in theponentDidMount()
function
More generally, the React Component Lifecycle is a very insightful source to understand the various functions that are executed when displaying and updating a React ponent. You may find this example useful too.
One your data has been loaded, then update the state
of your ponent with the data you obtain. Updating the state
(or props
) of a React ponent automatically triggers its render()
function and display your changes.
Then, in the render()
function, just return the DOM elements (or React ponents) to display based on the ponent's state variable. In the following example, we download JSON data (posts) from a URL using XMLHttpRequest
and return the title
of each post. We tell render()
to check the length of the posts
array in order to know if we have posts to display.
You can run the code snippet directly, data is JSON based (not XML), but I'm sure you can adapt it to your case.
class EditFiles extends React.Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
ponentDidMount() {
var xhttp = new XMLHttpRequest();
var self = this;
xhttp.onreadystatechange = function(e){
console.log(this);
if (xhttp.readyState === 4 && xhttp.status === 200){
console.log("ok, response :", this.response);
self.setState({
posts: JSON.parse(this.response)
});
}
}
xhttp.open("get", "https://jsonplaceholder.typicode./posts", true);
xhttp.send();
}
render() {
let postsLoaded = this.state.posts.length > 0;
return(
postsLoaded ?
<ul>
{
this.state.posts.map(
post => {
return <li>{ post.title }</li>;
})
}
</ul>
:
<div>Loading...</div>
);
}
}
ReactDOM.render(
<EditFiles />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your ponent. -->
</div>
Hope this helps!