14

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.

Naftali
  • 144,921
  • 39
  • 244
  • 303
rubyu2
  • 270
  • 1
  • 3
  • 14
  • 1
    `this.comments.push(comment)` expression returns a new list but does not modify the list in place (by definition, since it's immutable) – zerkms Aug 23 '15 at 10:10
  • I learned this way from http://facebook.github.io/react/docs/advanced-performance.html#immutable-js-and-flux. – rubyu2 Aug 23 '15 at 10:30
  • In that very article they assign the result of the call to the property itself. – zerkms Aug 23 '15 at 10:31
  • "Note that since the data structures are immutable, we need to assign the result of the push function to this.messages." Please go through that article one more time. – zerkms Aug 23 '15 at 10:56
  • Thank you.I think I misunderstood the immutable. – rubyu2 Aug 23 '15 at 11:05
  • I found the problem.Using `push` for immutable record is no problem, it always return a new immutable record.Before the constructor of CommentStore.`constructor(){this.comments = []}`. – rubyu2 Aug 23 '15 at 11:30
  • It always indeed returns a new immutable, but you don't assign it to anywhere. – zerkms Aug 23 '15 at 20:13
  • No.So the `comments constructor` was `function Array()`.I have changed the CommentStore to `constructor(){ this.comments = Immutable.List(); }`.There is no warning now. – rubyu2 Aug 23 '15 at 23:10
  • @Brad did you really add the solution to the question? – Naftali Nov 22 '16 at 19:35

2 Answers2

17

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
Mark Murphy
  • 2,834
  • 1
  • 31
  • 29
0

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>
Sadik
  • 245
  • 1
  • 3
  • 13