rubyu2
rubyu2

Reputation: 270

Using PropTypes when immutable-js in react-js

I am using immutable-js and react-immutable-proptypes in React.

// CommentBox.jsx
getInitialState() {
    return {
        comments: Immutable.List.of(
            {author: 'Pete Hunt', text: 'Hey there!'},
            {author: 'Justin Gordon', text: 'Aloha from @railsonmaui'}
        )
    };
},
render(){
    console.log(this.state.comments.constructor);
    return (
      <div className='commentBox container'>
        <h1>Comments</h1>
        <CommentForm url={this.props.url} />
        <CommentList comments={this.state.comments} />
      </div>
    );
}


// CommentList.jsx
propTypes: {
    comments: React.PropTypes.instanceOf(Immutable.List),
},

// CommentStore.js
handleAddComment(comment) {
    this.comments.push(comment);
}

When the page initialization, it's no problem,all is ok,no warning. The console log shows the comments is function List(value). When I add a new comment, it looks work well,but there is a warning

Warning: Failed propType: Invalid prop comments supplied to CommentList, expected instance of List. Check the render method of CommentBox.

and the console log shows that the comments is function Array(). So, why does the comments constructor change from List to Array?

And and I have read http://facebook.github.io/react/docs/advanced-performance.html#immutable-js-and-flux.

The messages store could keep track of the users and messages using two lists:

this.users = Immutable.List();
this.messages = Immutable.List();

It should be pretty straightforward to implement functions to process each payload type. For instance, when the store sees a payload representing a new message, we can just create a new record and append it to the messages list:

this.messages = this.messages.push(new Message({
  timestamp: payload.timestamp,
  sender: payload.sender,
  text: payload.text
});

Note that since the data structures are immutable, we need to assign the result of the push function to this.messages.

Upvotes: 14

Views: 11452

Answers (2)

Mehdiyev
Mehdiyev

Reputation: 245

You can specify a custom validator.

propName: function(props, propName, componentName) {
  if (!List.isList(props[propName]) && !Array.isArray(props[propName])) {
    return new Error(
      'Invalid prop `' + propName + '` supplied to' +
      ' `' + componentName + '`. Validation failed.'
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js"></script>

Upvotes: 0

Mark Murphy
Mark Murphy

Reputation: 2874

I came here looking to find a solution that would allow either an array or any sort of iterable object from ImmutableJS to be passed as the prop. In case anyone else finds this useful, here's what I came up with:

PropTypes.oneOfType([
  PropTypes.instanceOf(Array),
  PropTypes.instanceOf(Immutable.Iterable)
]).isRequired

Upvotes: 17

Related Questions