g3blv g3blv - 2 months ago 35
React JSX Question

Rendering an Array with React Async is Undefined

I am retrieving data from a REST service. The data comes back as an array. This is the function I use to retrieve the data.

export function fetchMessage() {
return function(dispatch) {
axios.get(`${ROOT_URL}/currencies`, {
headers: { token: localStorage.getItem('token') }
})
.then(response => {
console.log(response.data);
dispatch({
type: FETCH_MESSAGE,
payload: response.data
});
});
}
}


The output from
fetchMessage
is an array of Objects.

[Object, Object, Object, Object, Object, Object]
0:Object
addedDate:"2013-08-22"
ccyCode:"CHF"
country:"SCHWIZER FRANC"
lastChangeDate:"2016-05-02"
offerRate:7.02
prevRate:8.501
prevRateDate:"2016-04-01"
rate:8.425
rateDate:"2016-05-01"
unit:1
__proto__:Object
1:Object
2:Object
3:Object
4:Object
5:Object


The
fetchMessage
function is called by the component below.

class Feature extends Component {
componentWillMount() {
this.props.fetchMessage();
//console.log(this.props);
}

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

function mapStateToProps(state) {
return { message: state.auth.message };
}

export default connect(mapStateToProps, actions)(Feature);


The component can't render the message because it is an

bundle.js:1256 Uncaught (in promise) Error: Objects are not valid as a React child (found: object with keys {ccyCode, country, unit, rateDate, rate, prevRateDate, prevRate, offerRate, addedDate, lastChangeDate}). 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 `Feature`.(…)


I've tried to run a map of the
this.props.message
like this

<div>
{this.props.message.map(
function(object){
return ('Something'
);
}
)}
</div>


But I get an error message saying that I can't run
map
on
message
. How can I render the data in the object? Do I need to save it in some other way? How do I iterate over the objects to render them?

Answer

Update: I think your issue is just that this.props.message is undefined on the initial render. Try rendering null if it's not set.

render() {
  if (!this.props.message) return null
  return (
    <div>
      {this.props.message.map(message => {
        return (
          <div key={message.ccyCode}>...</div>
        )
      }}
    </div>
  )
}

My answer below might still be helpful if anyone is interested in dynamically rendering an Object.

I'm assuming you want to dynamically render the data from the objects, as opposed to having to explicitly render each field.

Try iterating through Object.keys and render the data.

<div>
    {Object.keys(this.props.message).map(key => {
        return (
          <div key={key}> // you need a dynamic, unique key here to not get a React warning
            {key}: {this.props.message[key]}
          </div>
        )
      }
    )}
</div>

If you want to just show the data for debugging/inspection purposes, I've found this is very helpful.

<pre>
  {JSON.stringify(this.props.message,null,2)}
</pre>