Home > database >  Why is my component not rerendering in this todo list app?
Why is my component not rerendering in this todo list app?

Time:01-17

From what I understand about mobx, the observable (the task list) should cause the observer(the TaskList component) to rerender when it changes. The action (pushing the task data into the task observable state) should change the observable, no? When I console log the data in taskList, I can see it. But nothing actually renders on the page, and I suspect it's because I'm not using the observer/observables correctly.

My code:

interface Task {
  task: string;
}
export default observer(function TaskList() {
  const [update, setUpdate] = useState<string>('');
  const taskList = makeAutoObservable({ tasks: [] as Task[] });
  useEffect(() => {
    fetchData();
  }, []);

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

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

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

CodePudding user response:

You cannot create store in the render process of the component like that, because when new data comes this store will be recreated again and it will be empty. Store should either be in the state to be persistent or as a singleton outside of React component at all:

  const [taskList] = useState(makeAutoObservable({ tasks: [] as Task[] });)

or just move it outside

const taskList = makeAutoObservable({ tasks: [] as Task[] });

export default observer(function TaskList() {
  const [update, setUpdate] = useState<string>('');
  
  useEffect(() => {
    fetchData();
  }, []);

CodePudding user response:

You have to use a useState for the taskList variable if you want to use it inside observer:

const [taskList, setTaskList] = makeAutoObservable({ tasks: [] as Task[] });
  useEffect(() => {
    fetchData();
  }, []);

  const fetchData = async () => {
    try {
      const response: any = await axios.get('http://localhost:5000/data');
      action(() => {
        const newTaskList = {...taskList} // copy the original state to other to generate new state event on set it
        newTaskList.tasks.push(...response.data.recordset);
        setTaskList(newTaskList);
      })();
    } catch (error) {
      console.error(error);
    }
  };
  • Related