tom_son
tom_son

Reputation: 135

MobX array of object is not re-rendering after a property in object is update

This Component renders a table with 1 cell with the value of "A".

How do i get my table to react to the value change of this.value[0].name after i click on the "Add character" button?

Currently when i click on the Add character button 2 times, i can see the value of name changes from "A" to "ABB" through the console.log inside onClickAddCharacter(). However, the table being rendered does not reflect this "ABB" new value, instead it is still "A". The strange thing is if i uncomment the console.log in the render() and click on the Add character button once, the cell value will re-render from "A" to "AB".

What is happening here and what am i doing wrong?

Thanks you!

EDIT: I'm using MobX 5

import Button from 'main/component/Button';
import {action, observable} from 'mobx';
import {observer} from 'mobx-react';
import {Column} from 'primereact/column';
import {DataTable} from 'primereact/datatable';
import React from 'react';

@observer
class Component extends React.Component
{
    @observable
    private value = [{ name: 'A' }];

    @action.bound
    private onClickAddCharacter()
    {
        this.value[0].name += 'B';
        console.log(this.value);
    }

    render()
    {
        // If uncomment, the cell value will re-render from "A" to "AB"?
        // console.log(this.value);
        return (
            <>
                <DataTable value={this.value}>
                    <Column header='Name' field='name' />
                </DataTable>
                <Button title='Add character' onClick={this.onClickAddCharacter} />
            </>
        );
    }
}

Upvotes: 1

Views: 2194

Answers (1)

Danila
Danila

Reputation: 18556

Because your DataTable from primereact is not observer by itself you need to use toJS MobX method on your data before you pass it to DataTable.

import { toJS } from "mobx";

// ...

@observer
class Component extends React.Component
{
    @observable
    private value = [{ name: 'A' }];

    @action.bound
    private onClickAddCharacter()
    {
        this.value[0].name += 'B';
        console.log(this.value);
    }

    render()
    {
        return (
            <>
                <DataTable value={toJS(this.value)}>
                    <Column header='Name' field='name' />
                </DataTable>
                <Button title='Add character' onClick={this.onClickAddCharacter} />
            </>
        );
    }
}

Upvotes: 3

Related Questions