1

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?

2
  • Try something like this: <div>{this.props.message.ccyCode} {this.props.message.rate}</div> and go from there. Commented Sep 30, 2016 at 11:55
  • @ChrisG I tried both <div>{this.props.message.ccyCod}</div> and <div>{this.props.message.rate}</div> and both gives the error message Uncaught TypeError: Cannot read property 'rate' of undefined the undefined property of course change to ccyCode when I try with ccyCode. Commented Sep 30, 2016 at 12:24

1 Answer 1

4

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}>...
            {message.ccyCode} {message.rate} ...
          </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>
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for the suggestions Brad. The JSON Stringify renders the whole object. But when I try the Object.keys setting <div key={ccyCode}> then I get ReferenceError: ccyCode is not defined. I don't understand what you mean by "undefined on the initial render"? Is there a second render? Using the if statement I guess will just result in nothing/null being rendered?
First off, where is ccyCode defined? Typically you use a value from the mapped record. So you might just need to reference it like this.props.message[key].ccyCode. Second, Because you're calling the API async in componentWillMount(), it will render initially without the data, and then a 2nd time when the response updates state.
Also, my response was assuming you wanted to render an Object, per your question. If you're wanting to render all of the array results, I think the error should clear up when you fix that initial render error.
Thanks Brad. I changed to ` <div key={this.props.message[key].ccyCode}> {key}: {this.props.message[key].ccyCode} </div>` which give the output 0: CHF 1: DKK 2: EUR... Just what I want. Just a one questions I set my key with key={this.props.message[key].ccyCode} but then when I use ` {key}` then the output is a number. What is it that I'm missing in my understanding?
Its hard to say.. are you wanting to dynamically iterate through all fields of an object, or all the objects in the array? Are you using Object.keys are still just the map?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.