0

From the extent of my knowledge, action in mobx is supposed to cause the observer to rerender, right? However, even though I'm invoking action on the handleSubmit method in my AddTask component, it does not rerender the observer(TaskList). Do I have to wrap AddTask in an observable as well? But when I tried that, it didn't render any of the data at all. I'm genuinely perplexed and have tried so many different things for hours. Please help.

AddTask:

export default function AddTask() {
  const [task, setTask] = useState('');
  const handleSubmit = action(async (event: any) => {
    event.preventDefault();
    try {
      const response = await axios.post('http://localhost:5000/test', { task });
    } catch (error: Error | any) {
      console.log(error);
    }
  });

  const onChange = (e: any) => {
    const value = e.target.value;

    if (value === null || value === undefined || value === '') {
      return;
    }

    setTask(value);
  };

  return (
    <div className="task">
      <form onSubmit={handleSubmit}>
        <input type="text" name="task" value={task} onChange={onChange}></input>
        <br></br>
        <input type="submit" name="submit" value="Submit" />
      </form>
    </div>
  );
}

TaskList:

const TaskList = () => {
  const [update, setUpdate] = useState<string>('');

  useEffect(() => {
    TaskStore.fetchTasks();
  }, []);

  const onChangeValue = (e: any) => {
    setUpdate(e.target.value);
  };

  return (
    <div>
      <p>
        update input <input onChange={onChangeValue} value={update} />
      </p>
      {TaskStore.tasks.map((value: any, key) => {
        console.log(value);
        return (
          <div key={key}>
            <p>
              {value.task}
              <DeleteTask value={value} taskList={TaskStore} />
              <UpdateTask value={update} current={value} taskList={TaskStore} />
            </p>
          </div>
        );
      })}
    </div>
  );
};

export default observer(TaskList);

taskStore:

interface Task {
  task: string;
}

class TaskStore {
  constructor() {
    makeAutoObservable(this);
  }
  tasks = [] as Task[];

  @action fetchTasks = async () => {
    try {
      const response: any = await axios.get('http://localhost:5000/test');
      this.tasks.push(...response.data.recordset);
    } catch (error) {
      console.error(error);
    }
  };
}

export default new TaskStore();
Chan Kim
  • 159
  • 8

1 Answers1

0

As far as I can see you are not doing anything in your submit action to handle new task.

You are making request to create new task, but then nothing, you don't do anything to actually add this task to your store on the client nor make store refetch tasks.

  const handleSubmit = action(async (event: any) => {
    event.preventDefault();
    try {
      // Request to create new task, all good
      const response = await axios.post('http://localhost:5000/test', { task 
      
      // Now you need to do something
      // 1) Either just add task to the store manually
      // Add some action to the store to handle just one task
      TaskStore.addTask(response.data)

      // 2) Or you can do lazy thing and just make store refetch everything :)
      // Don't forget to adjust this action to clear old tasks first
      TaskStore.fetchTasks()
});
    } catch (error: Error | any) {
      console.log(error);
    }
  });

P.S. your action decorators are a bit useless, because you cannot use actions like that for async function, for more info you can read my other answer here MobX: Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed

Danila
  • 15,606
  • 2
  • 35
  • 67