Search code examples
reactjsmobxmobx-react

Is it safe to pass mobx observable objects as props to react components


Say, I've a Product model which has 10+ attributes and some of them are also objects .

{
  "product": {
    "name": "shoe",
    "brand": "....",
    "categories": {
      "abc": {
        ...
      }
    },
    ...
  }
}

I need to update the Product in a react component, however, product also has some children to be viewed/changed by other components.

@observer
class ProductContainer extends Component {

    @observable product;

    render() {
        return (
            <ProductDetails product={product} />
        )
    }
}


@observer
class ProductDetails extends Component {

    static propTypes = {
        product: PropTypes.any
    }

    @autobind
    @action
    handleChangeName(event) {
        const {product} = this.props;
        product.name = event.target.value;
    }

    render() {
        const {product} = this.props;
        return (
            <form>
                <label>Name: <input type="text" onChange={this.handleChangeName} /> </label>
                <CategoryView categories={product.categories} />
            </form>
        );
    }
}


As seen in the example I've inner components such as CategoryView to which I pass an observable object's child (which is observable as well).

What I do in the example is I do not change the product prop reference but change it's children and attributes (such as name).

React says that props should be immutable, however the example below works just fine. Is it safe to do that tho?


Solution

  • That's totally fine with MobX, it is the right way.

    Sometimes you don't want to change attributes like this, but create some sort of Model wrapper around your data (something like https://github.com/mobxjs/mobx-state-tree or its alternatives) and use Model methods to change stuff. But your example is ok too.

    Although you need to wrap ProductDetails with observer decorator so it could react to changes. (maybe you just omitted it in your example)