I'm currently working on a school project where I have to make a simple CRUD webapp, and I've decided to go with Spring Boot + ReactJS. Pretty much everything is in order, except that I've e to realize I've made part of the React code work without really knowing what's going on (I've mainly pieced together a solution from different tutorials and official documentation).
So, the API contains two messages like so:
"messages": [
{
"message": "first message",
"user": "Silb",
},
{
"message": "second message",
"user": "Silb",
}
]
I'm currently working on a school project where I have to make a simple CRUD webapp, and I've decided to go with Spring Boot + ReactJS. Pretty much everything is in order, except that I've e to realize I've made part of the React code work without really knowing what's going on (I've mainly pieced together a solution from different tutorials and official documentation).
So, the API contains two messages like so:
"messages": [
{
"message": "first message",
"user": "Silb",
},
{
"message": "second message",
"user": "Silb",
}
]
And my React code looks like this:
const api = 'http://localhost:8080/api/messages/';
class Content extends React.Component {
constructor(props) {
super(props)
this.state = {
messages: []
};
}
ponentDidMount() {
fetch(api)
.then(response => response.json())
.then(data => {
this.setState(data);
})
}
render() {
return(
//Here is where the data from the API should be displayed
<div className="newmessage">
<p>User: </p>
<p>Message:</p>
</div>
)
}
}
Now, what I understand is that the fetch grabs the data from the API, puts it in the response
variable, parses it to JSON, but after that, what does the data
variable represent? Do I even need it?
If I console.log data alone, the console will return the JSON, without any problem and I can even display one message by calling this.state.message and this.state.user, but I really don't understand what I need to do to loop through each message so I can display each separately with a .map() function.
I read the following answer: How to map a JSON array to a List in ReactJS?
and I think I have a vague understanding of how map works, but I still haven't been able to create an array with my JSON data. I think I have to get the data
into the messages: []
array that I initialized in the constructor, so I then can create a newmessage
div with each individual message from the array, with each its own unique id. Am I correct?
I'm sorry if my questions are convoluted, I've kinda been at it for most of this weekend and I can't for the love of me just understand what's going on here.
I thank in advance and greatly appreciate your patience, and I'm grateful for any tips/help!
EDIT: I forgot to mention that if I fetch 'http://localhost:8080/api/messages/1', i.e. the first message, I can succesfully display it on the div using {this.state.user}
and {this.state.message}
, but not if i just call /api/messages/
- Can you please provide the structure of the "Data" object ad i can solve it for you. irrespective of the structure, you can understand array#map easily but just thinking of it as - "apply this function to every element of a array", you can change the this.setState(data) call to this.setState({messages: data}) assuming data is an array, if data is an object with an array inside it you'll need to parse it into an array first. – Shanon Jackson Commented Feb 11, 2018 at 22:14
-
The structure of the
Data
object I assume is the JSON response, right? If so it looks like this: codeshare.io/2KwbQY – Silberio Commented Feb 12, 2018 at 13:06 - I'm not sure what I'm doing wrong, as I keep getting "this.state.messages" is undefined, although I do define it at constructor and then with setState({messages: data.messages}); and I've tried both approaches that you, and Miguel have explained. Could it be that my API isn't returning a proper JSON object or so? – Silberio Commented Feb 12, 2018 at 13:11
2 Answers
Reset to default 4Your question is clear. What you usually do is iterate the this.state.messages
array in the ponent's render()
function and return a new child ponent with each array entry, like this:
{ this.state.messages.map((message, index) => (
<div className="newMessage" key={index}>
<p>User: {message.user}</p>
<p>Message: {message.message}</p>
</div>
))}
Javascript's map
function iterates the array and calls the provided function with three arguments, the first of them being the array entry being traversed, which is the only one we need here. The function returns the element transformed as you need; in this case, you transform it into a JSX / React ponent.
A key
prop is added to each div
child of the mapped Array
as required by React (see https://reactjs/docs/lists-and-keys.html#keys). We are using Array
indexes as keys, contrary to the remended practice, because we don't have other data to uniquely identify each child - you could hash the user name and message, for example, but that sounds overkill.
from what i can tell from the structure of you're data you want something like this, where the setState call has changed, and the markup in you're render method but nothing else.
array#map as per my ment can be understood by thinking about it as "apply a function to each element in an array" in this code it can be thought of as "apply a function that takes a message obj and applies a function that turns that message obj into a JSX object"
const api = 'http://localhost:8080/api/messages/';
class Content extends React.Component {
constructor(props) {
super(props)
this.state = {
messages: []
};
}
ponentDidMount() {
fetch(api)
.then(response => response.json())
.then(data => {
this.setState({messages: data.messages});
})
}
render() {
return(
//Here is where the data from the API should be displayed
<div className="newmessage">
{this.state.messages.map((messageObj) => {
return (
<div>
<p>user: {messageObj.user}</p>
<p>message: {messageObj.message}</p>
</div>
);
}}
</div>
)
}
}