3

I can not get the truth why the TableContainer|TableComponent component does not update its children properly.In a store i have an array of objects,when i am trying to update object property the Table does not update its values.If i replace whole array it is working though.

You can check this behaviour in this sandbox.

Documentation states that initiating observable array,makes items observable too.(docs)

Similar to objects, arrays can be made observable using observable.array(values?) or by passing an array to observable. This works recursively as well, so all (future) values of the array will also be observable.

Why is this happening?i am coming from redux background and i am trying to wrap my head around mobx with no much of success.

Jan Ciołek
  • 1,796
  • 3
  • 17
  • 32

2 Answers2

4

Your FlipScrollTable component should be an observer as well

mweststrate
  • 4,890
  • 1
  • 16
  • 26
  • 1
    Thanks that would do it but that is quite strange, i would like to have this "dumb" component to stay dumb.Is there any other solution to this?correct me if i am wrong but presentational components should not have such logic.The presentational component should not be responsible for this.This solution breaks the [smart&dumb components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) pattern.Should this pattern apply to mobx? – Jan Ciołek Aug 25 '18 at 15:23
  • If you want to benefit from observable data being observable, you have to use observers. Otherwise you should not be passing observable data into the 'dumb' component, but plain data instead. It is like passing an RXJS stream in, but never subscribing. – mweststrate Aug 27 '18 at 12:27
  • Thanks, i will try to dig into the mobx a little bit more.Cheers – Jan Ciołek Aug 28 '18 at 11:56
1

Try adding your injection directly to the TableComponent, for a stateless solution:

@inject("store")
@observer
class FlipScrollTable extends React.Component {
  componentDidMount() {}

  render() {
    var { columns, header } = this.props;
    var { array } = this.props.store;
    const classes = {};
    return (
      <table>
        <thead>
          <tr>
            {columns.map((column, i) => {
              var { header, headerStyle } = column;
              return (
                <th key={i} style={headerStyle}>
                  {header}
                </th>
              );
            })}
          </tr>
        </thead>
        <tbody>
          {array.map(row => {
            var tableCells = columns.map(column => {
              var { accessor, id, Value } = column;
              var value = _isFunction(accessor)
                ? accessor(row)
                : _get(row, accessor);

              var renderedValue = normalizeComponent(
                Value,
                { value, row },
                value
              );

              return (
                <td key={_isFunction(accessor) ? id : accessor}>
                  {renderedValue}
                </td>
              );
            });
            return <tr key={row.id}>{tableCells}</tr>;
          })}
        </tbody>
      </table>
    );
  }
}

With reference with your sandbox, it appears that you are attempting to change a component after it has been rendered; where you should re-render components directly from the observable array changes.

Jason Mullings
  • 850
  • 14
  • 10
  • Thanks @Jason Mullings.The @mwestrate provided same solution but this somewhat breaks [smart&dumb](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) components pattern.Anyway the column `Value` renderer is wrapped in the Observer component.Cheers! – Jan Ciołek Aug 27 '18 at 07:32
  • Try to imagine each component is an image! It can only be created by the information/ data injected into it. If you continue envisioning component as / like you'll only serve to limit your scope of functionality. This might help to expand upon what I'm referring to: https://github.com/jmullings/react101 – Jason Mullings Aug 27 '18 at 07:41