I have a table component I've built for my app that leverages mobx and works fine. I want to add in the ability to update objects inside the tables data without reloading the page. The setup currently looks like this (simplified):
export const SmartTable = observer(class SmartTable extends Component {
dataRows = []
selectedRows = []
fetchData = async () => {
this.loading = true;
this.dataRows.clear();
const response = await client.get(this.props.dataUrl, params);
for (const row of response.data.map(item => new this.props.model(item))) {
this.dataRows.push(row)
}
this.loading = false;
}
render() {
<BootstrapTable
data={this.dataRows}
columns={this.dataColumns}
selectRow={this.props.actions && {
mode: 'checkbox',
onSelect: (row, isSelect, rowIndex, e) => {
if (isSelect) {
this.selectedRows.push(row);
} else {
const filteredObjects = this.selectedRows.filter((r) => r.id !== row.id);
this.selectedRows.replace(filteredObjects);
}
},
onSelectAll: (isSelect, rows, e) => {
if (isSelect) {
this.selectedRows.replace(rows);
} else {
this.selectedRows.replace([]);
}
},
}}
/>
}
})
decorate(SmartTable, {
dataCols: observable,
dataRows: observable,
selectedRows: observable,
});
I have models that look like this:
import { action, computed, observable } from "mobx"
export class Earning {
id = null
@observable amount
@observable status
constructor(data) {
this.id = data?.id
this.updateFromJson(data)
}
@computed get asJson() {
return {
id: this.id,
amount: this.amount,
status: this.status,
}
}
@action updateFromJson(data) {
this.id = data.id
this.amount = data.attributes.amount
this.status = data.attributes.status
}
}
Inside my code, I use the SmartTable and render a button into the column to approve the earning:
export const EarningsTable = observer(class EarningsTable extends Component {
approveAllEarnings = async (earnings) => {
if (window.confirm('Are you sure you want to approve all selected earnings?')) {
await Promise.allSettled(earnings.map(async (earning) => {
await client.put(`/earnings/${earning.id}/`, { earning: { status: 'approved' } });
runInAction(() => {earning.status = 'approved'});
}))
}
}
columns = [
{
dataField: 'id',
text: 'ID',
formatter: this.idFormatter,
sort: true,
headerStyle: () => ({ width: '100px' }),
},
{
dataField: 'amount',
text: 'Amount',
formatter: this.amountFormatter,
sort: true,
},
{
dataField: 'status',
text: 'Status',
sort: true,
formatter: this.statusFormatter,
headerStyle: () => ({ width: '90px' }),
},
{
dataField: '',
text: 'Actions',
formatter: this.approveButton,
},
]
render() {
return (
<SmartTable
model={Earning}
dataUrl={this.props.dataUrl}
columns={this.columns}
actions={{
'Approve Checked': earnings => this.approveAllEarnings(earnings),
}}
/>
);
}
});
decorate(EarningsTable, {
approveAllEarnings: action,
});
When I click the button to "approve" the earning, the Earning model gets updated properly, but the table doesn't update. Is there a way to get this working?
reproducible example: https://codesandbox.io/s/hopeful-forest-hq9kf