arqex / freezer

A tree data structure that emits events on updates, even if the modification is triggered by one of the leaves, making it easier to think in a reactive way.
MIT License
1.28k stars 56 forks source link

While using with react I need to pass the parent of the data #39

Closed panbhag closed 8 years ago

panbhag commented 9 years ago

When I am using Freezer with React, and if I am passing a string/number as props, then, I cannot update the prop in the React component, as in Freezer we need a parent component to set the value of the leaf nodes. That would make the code quite complex. Whats the way out

arqex commented 9 years ago

Hi @panbhag

It is easier if you trick your mind to understand the inner nodes of a freezer tree as entities and the leaf of the trees as properties of the entites. For example

{ dog: {
  color: 'brown',
  size: 'small',
  age: 5
}}

In this case the entity would be dog and it would have a react component to update the dog. color, size and age wouldn't have their own component, and they would be updated updating dog.

If you need to have a react component for any of the properties, let's imagine a colorpicker for the colorproperty, it should expose a change property to let the dog update on color change:

class Dog extends React.Component {
    render(){
        return (
            <div className="dog">
                <ColorPicker value={ this.props.model.color } onChange={ this.updateColor.bind( this ) } />
            </div>
        );
    },
    updateColor( color ){
        this.props.model.set( {color: color} );
    }
}

But it would be the dog the one who would update the its own color property.

panbhag commented 9 years ago

Hi @arqex Thanks for the reply, In the above example, it becomes an issue, when I need to load dog from an API, initially dog object is null, and later after the api call it needs to be updated, in which case I cannot do it from inside the component.

   var data = new Freezer({dog:null});
   <Dog dog=data.get().dog/>

    //inside Dog
   componentDidMount:function(){

       //API call => apiDogObject
          //how do i update the the dog in data here
  }

I can update it as you demonstrated in the second method by passing it a callback, but that becomes too cumbersome.

arqex commented 9 years ago

I recommend to not fetch the data from inside the Dog component but in the parent one, so the dog data is going to be always available. But in case you need to fetch the data from inside the component you can set you dog to {} and you will be able to reset the data when it is available:

 var data = new Freezer({dog:{}});
   <Dog dog=data.get().dog/>

    //inside Dog
   componentDidMount:function(){
       var me = this;
       API.get('dog').then( function( data ){
         me.props.dog.reset( data );
      });
  }
panbhag commented 9 years ago

Thanks, I have started using flux(reflux) and now all data modification operations are in store, so my problem is solved. Thanks again for your quick replies!