MobX - Map with extendObservable not rerending with new value?

1k views Asked by At

So in mobx when you add new fields to an observable, via extendObservable it does not rerender the component, and the idea is to use an observable map instead, which should pick up the new changes (keys/values) and rerender the component.

On load of the component, I see the Name and the Language values assigned in the constructor. So that's working as expected. Perfect!

The issue is after assigning the new field Year below via the button using the addYear action, I am able to alert out the value for it, which means it is in the map, which should rerender the component, but it does not. Here is the code:

@observer
export default class Book extends Component {
    @observable book = asMap({});

    constructor(props){
      super(props);

      const map = this.book;
      map.set('book', {name: 'The Secret', language: 'English'});
    }

    @action addYear() {
      const year = {year: '2006'};

      const map = this.book;
      if (map.has('book')) {
        extendObservable(map.get('book'), toJS(year));
        alert(map.get('book').year); // Shows Year but does not rerender
      }
    }

    render() {
      const map = this.book;
      const book = map.has('book') && map.get('book');

      return (
        <View style={styles.wrapper}>
            <TouchableOpacity style={styles.button}
                              onPress={() => this.addYear()}>
                <Text style={styles.text}>Add Year!</Text>
            </TouchableOpacity>

            <Text>Name: {book.name}</Text>
            <Text>Language: {book.language}</Text>
            <Text>Year: {book.year}</Text>
        </View>
      )
    }
}

Any idea why it's not rerendering the component on addition of Year to the book map?

1

There are 1 answers

1
Tholle On BEST ANSWER

If you just have a map representing a book, you could just set the year property like this:

@observer
class App extends React.Component {
  @observable book = asMap({
    name: 'The Secret', 
    language: 'English'
  });
  addYear = () => {
    this.book.set('year', '2006');
  };
  render() {
     const year = this.book.get('year');
     return <div> 
       <div>Name: {this.book.get('name')}</div>
       <div>Language: {this.book.get('language')}</div>
       {year ? <div>Published Year: {year}</div> : null}
       <button onClick={this.addYear}> Add Year </button>
     </div>;
  }
}