0

I have a list of todos in store which is not sorted. A computed value is added to store that returns sorted todos. The React Component is using sortedTodos to display the list. Whenever the todos list changes, the component is not re-rendered, if I use todos directly it works.

export class TodoStore {
  @observable todos: Todo[] = [
    { description: "testing", createdAt: new Date(), isCompleted: false },
  ];

  @computed get sortedTodos(): Todo[] {
    const sortedTodos = this.todos.sort(
      (a, b) => a.createdAt.getTime() - b.createdAt.getTime()
    );
    return sortedTodos;
  }

  @action addTodo = (description: string) => {
    this.todos.push({
      description,
      createdAt: new Date(),
      isCompleted: false,
    });
  };
}

Gurleen Sethi
  • 3,162
  • 6
  • 26
  • 48
  • 1
    I'm not familiar with mobx, but I do know react does shallow reference equality checks of state/props to determine if a component should rerender. Arrays are sorted in place, so the array reference doesn't change. If `sortedTodos` returns a *new* array it may work. – Drew Reese Apr 11 '20 at 06:59
  • Your mobx code is correct. Can you post component code or make a reproduction on codesandbox? – Ivan V. Apr 12 '20 at 12:00

1 Answers1

0

I found the solution for the problem.

Instead of directly assigning an array, I used observable.array and it works.

export class TodoStore {
  @observable todos: Todo[] = observable.array();

  ...
}

Not completely sure why so but it works. I think the reason is that by using a regular array, the objects inside are not observables by default, when using observable.array the objects of array themselves are observables.

Gurleen Sethi
  • 3,162
  • 6
  • 26
  • 48
  • You can then you remove `@observable` decorator. – Ivan V. Apr 13 '20 at 17:31
  • @IvanV. Is there a decorator that would take care of this behaviour i.e. it could make the children of array observables as well. – Gurleen Sethi Apr 13 '20 at 19:06
  • It is strange that the `@decorator` is not working in the first place. Also `observable` and `observable.array` are `deep` by default, meaning that anything added to the array will also be made observable. I still think that you have an error in the way how you are using the observables in react components. The original code you posted works as expected. – Ivan V. Apr 13 '20 at 19:51