Search code examples
javascriptreactjsmobxmobx-reactmobx-state-tree

convert react app using this.state to mobx


i have created a ToDo list in javascript using react,since i am a beginner in react i have used 'this.state' to change the state of my app in multiple components,my issue is that at a job interview i was given a task to create the todo list with the use of mobx to run its state,however after a long research i am still having a lot of issues of converting my react project's 'this.state.todo',here is the main app component in code,i whould love a demonstration in how to convert the state to mobx observer/observable ,if more components are needed i whould love to add them

import React from 'react';
import _ from 'lodash';
import TodoCreate from './todo-create';
import TodoList from './todo-list';
import 'semantic-ui-css/semantic.min.css';
import { Header } from 'semantic-ui-react';
import {decorate, observable} from "mobx"
import {observer} from "mobx-react"
export default class App extends 
React.Component {

constructor(props) {
    super(props);

    this.state = {
       todos : todos
    }

    this.createTask = this.createTask.bind(this);
    this.saveTask = this.saveTask.bind(this);
    this.deleteTask = this.deleteTask.bind(this);
    this.toggleTask = this.toggleTask.bind(this);
}

createTask(task) {
    this.state.todos.push({
        task,
        isCompleted: false,
        creationDate:new Date().toLocaleTimeString() + new Date().toLocaleDateString(),
        updateDate:new Date().toLocaleTimeString() +  new Date().toLocaleDateString()
    });
    this.setState({ todos: this.state.todos });
}

deleteTask(taskToDelete) {
    _.remove(this.state.todos, todo => todo.task === taskToDelete);
    this.setState({ todos: this.state.todos });
}

saveTask(oldTask, newTask) {
    const foundTodo = _.find(this.state.todos, todo => todo.task === oldTask);
    foundTodo.task = newTask;
    foundTodo.updateDate = new Date().toLocaleTimeString() +  new Date().toLocaleDateString();
    this.setState({ todos: this.state.todos });
}

toggleTask(task) {
    const foundTodo = _.find(this.state.todos, todo => todo.task === task);
    foundTodo.isCompleted = !foundTodo.isCompleted;
    foundTodo.updateDate = new Date().toLocaleTimeString() + '' + new Date().toLocaleDateString();
    this.setState({ todos: this.state.todos });
}

render() {
    return (
        <div>
            <div className="wrap">
            <div className="header">
                <Header as="h2" className="headerclass">ls-tech Todo-list</Header></div>
                  <div className="wrap-list">

            <div className="td-list-con">

                <TodoCreate
                    todos={this.state.todos}
                    createTask={ this.createTask}
                    />

                <TodoList
                    todos={ this.state.todos }
                    saveTask={ this.saveTask }
                    deleteTask={ this.deleteTask }
                    toggleTask={ this.toggleTask }
                    />
               </div>
            </div>
        </div>
    </div>
    )
}
}

Solution

  • So mobx is different than other state management systems common for react in that mobx encourages mutable state. So instead of having to do all the extra boilerplate to keep your state from being mutated, you just make changes by changing what you want to change the "easy" way.

    For example, say you have a collection of todo objects that have a description and isFinished property. In Mobx, you would simply take you todo item and todoItem.isFinished = true to set the todo item to true/checked. Mobx takes care of the rest, and notifies the relevant components to update. As a result, you rarely if ever need to call this.setState when using mobx. Any change (to an observable object) automatically updates state.

    If you weren't using Mobx you would need to make sure you never mutated a value, and instead returned a new copy of the object with the only difference being the change you wanted. I believe that's why you are using the methods on the _ object: they help you make a change without mutating values (although it looks like you are still accidentally mutating things).

    In exchange for this simplicity, you need to ensure a few things: the objects you are mutating need to be observable, and the components that render them need to be observers. (see the mobx documentation)

    Also, remember that mobx observes when properties are changed, not when variable values are changed. So mobx can observe this change: foo.bar = "new value" but not this change: let foo = 'initial value'; foo = 'new value' (notice the . in the first example).

    Because this is a test question, I won't fix your code for you, but I will refer you to the mobx example todo app, and hopefully that will help.