dwigt dwigt - 3 months ago 61
React JSX Question

Rendering JavaScript Object in React

I have a React project set up to fetch an Object from a Firebase database and render this to my page. However I do not know how to render the data properly.

The data I am fetching looks like this:

{
"projects": {
"0": {
"title": "test",
"function": "test2"
},
"1": {
"title": "test3",
"function": "test4"
}
}
}


In the Chrome React Debugger I see this:

<div>
<Message key="0" data={function: "test2", title: "test", key: "0"}>...</Message>
<Message key="1" data={function: "test4", title: "test3", key: "1"}>...</Message>
</div>


But in the elements view I am simply seeing two empty divs:

<div>
<div></div> == $0
<div></div>
</div>


Currently I am passing
<Message key={index} data={message} />
to a Message component containing
{this.props.data}


Refactoring the code to:
<div> key={index} data={message} </div>
however returns the error

Objects are not valid as a React child (found: object with keys {function, title, key}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of ProjectList.


Seeing as the project items have keys I do not believe CreateFragment is the correct solution. Also Firebase favors passing objects with keys over arrays so the solutions I am given does not seem to work in this situation. But how can I then control how the objects are rendered on the page?

My complete ProjectList component looks like this:

import React from 'react';
import firebase from 'firebase';
import _ from 'lodash';
import Message from './Message'

class ProjectList extends React.Component {
constructor(props){
super(props);
this.state = {
messages: {}
};

this.firebaseRef = firebase.database().ref('projects');
this.firebaseRef.on("child_added", (msg)=> {
if(this.state.messages[msg.key]){
return;
}

let msgVal = msg.val();
msgVal.key = msg.key;
this.state.messages[msgVal.key] = msgVal;
this.setState({messages: this.state.messages});
});
}

render(){
var messageNodes = _.values(this.state.messages).map((message, index)=> {
return (
<Message key={index} data={message} />
);
});

return (
<div>
{messageNodes}
</div>
);
}
}

export default ProjectList;


Thanks!

Edit: changed the Message component render to
{this.props.data}
as Message component receives no message prop.

Answer

Change your Message render method to:

render() {
  return <div>{this.props.data}</div>
}