DEV Community

cgokey
cgokey

Posted on

observed data reverting back in mobx-react with bootstrap-4

I've been seeing an issue in mobx-react with bootstrap-4 and I'm getting some unexpected results that is driving me crazy. I've boiled it down to the simple example below.

1) Model object that simply holds an array of data. And an action that provides a way to add data to the array.
2) App component that instantiates the model object and will render:

  • the model's data which is an array rendered as JSON string (that data is marked as observable).
  • A button to add a new object to model (the add is marked as an action in the model object) All this works fine, if I don't wrap the Button in a bootstrap4 Form, like below:
render() {    
    return (
      <>
          {JSON.stringify(this.model.data)}

          <Button onClick={this.addNewItem}>Add Another</Button>      
      </>
    )
  }
Enter fullscreen mode Exit fullscreen mode

But if the Button is wrapped in a bootstrap4 Form, you can see a slight delay where the JSON is changed to include the new item, but then instantly reverts back to the old data which does not include the new item.

render() {    
    return (
      <>
          {JSON.stringify(this.model.data)}

        <Form>
              <Button onClick={this.addNewItem}>Add Another</Button>
        </Form>


      </>
    )
  }
Enter fullscreen mode Exit fullscreen mode

Any idea what might be going on here? Full Source is below.
Thanks,
Chris

import React, { Component } from 'react';
import { observer } from 'mobx-react'
import { Card, Form, Button } from 'bootstrap-4-react';
import { action, makeObservable, observable } from 'mobx';

class Model {
  data = null
  constructor(data) {
      this.data = data

      makeObservable(this, {
          data: observable,
          add: action
      })
  }
  add() {
      this.data.push({ "Date": new Date() })
  }
}

class App extends Component {

  constructor(props) {
    super(props)
    this.addNewItem = this.addNewItem.bind(this);
    var data = [
      {
        "Date": new Date()
      }
    ]
    this.model = new Model(data)
  }

  addNewItem() {
    this.model.add()
  }

  render() {    
    return (
      <>
          {JSON.stringify(this.model.data)}

        <Form>
              <Button onClick={this.addNewItem}>Add Another</Button>
        </Form>


      </>
    )
  }
}

export default observer(App);
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
cgokey profile image
cgokey

Response from github.com/mobxjs/mobx/discussions...

Hi, it's not related to Mobx. If you don't provide action attribute on a form, it sends the data to current URL thus reloading page: developer.mozilla.org/en-US/docs/L...

"If this attribute isn't provided, the data will be sent to the URL of the page containing the form — the current page."

You can fix it by providing onSubmit attribute to prevent form submitting:

<Form onSubmit={(e) => { e.preventDefault() }}>
<Button onClick={this.addNewItem}>Add Another</Button>
</Form>

Here is a working example:
codesandbox.io/s/adoring-sky-xrwbp...