Home > Back-end >  Why is my data being duplicated when I fetch tasks with mobx action?
Why is my data being duplicated when I fetch tasks with mobx action?

Time:01-17

I have a todo list app and am trying to fetch the tasks from the backend when the component renders. However, the data is duplicated and I can't understand why. Could it be because the useEffect hook is being called twice? I suspect because when the observable changes, the observer rerenders so it might be being called a second time, but then wouldn't it become an infinite loop? So I don't quite understand.

TaskList.tsx:

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

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

  const onChangeValue = (e: any) => {
    console.log(e);
    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>
            <p>
              {value.task}
              <DeleteTask value={value} taskList={TaskStore} />
              <UpdateTask value={update} current={value} taskList={TaskStore} />
            </p>
          </div>
        );
      })}
    </div>
  );
};

export default observer(TaskList);

taskStore.ts:

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();

CodePudding user response:

This is due to react in development having Strict Mode enabled by default.

https://reactjs.org/docs/strict-mode.html

Which is meant to catch scenarios exactly like this where extra re-renders can cause problems.

To fix this, you should reinitialize the tasks array on every fetch. So something like this.

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

CodePudding user response:

I suspect it duplicates because of this line, in taskStore.ts this.tasks.push(...response.data.recordset);. try this.tasks = [...response.data.recordset]; instead. if the fetch call does not act like infinite scrolling, this approach is the best solution, in my opinion, it won't duplicate the data in dev mode when useEffect runs twice

  • Related