Как обновить массив данными из запроса на выборку axios и визуализировать с помощью перехватчиков React

#reactjs #axios #react-hooks

#reactjs #axios #react-перехваты

Вопрос:

Я извлекаю список активных задач из Todoist

 const [activeTasks, setActiveTasks] = useState([]);

  useEffect(() => {
    axios
      .get("https://api.todoist.com/rest/v1/tasks?project_id=111234345", {
        headers: {
          Authorization: "Bearer xxxAuthorisationCodexxx",
        },
      })
      .then((res) => setActiveTasks(res.data));
  }, []);
  

Обработайте результаты.

 const [allTasks, setAllTasks] = useState([]);  // flat list of all tasks
const [nestedAllTasks, setNestedAllTasks] = useState([]);  // Nested list of all tasks

useEffect(() => {
    let tasks = [];
    activeTasks.map((task) =>
       tasks.push({
         id: task.id,
         parent_id: task.parent_id,
         content: task.content,
         priority: task.priority,
         comments: [],
         complete: false,
       })
    );
    
    setAllTasks(tasks);
  }, [activeTasks, labels]);
  

Затем я пытаюсь выполнить итерацию allTasks и добавить комментарии, для каждого комментария требуется запрос на выборку на основе идентификатора задачи, который я инкапсулировал в getComments функцию.

 const getComments = useCallback(async (task_id) => {
    const comments = await axios.get(
      `https://api.todoist.com/rest/v1/comments?task_id=${task_id}`,
      {
        headers: {
          Authorization: "Bearer xxxAuthorisationCodexxx",
        },
      }
    );
    return comments;
  }, []);

useEffect(() => {
    let tasks = [...allTasks];  // shallow copy allTasks
     const getAllComments = () => {
       tasks.map(async (task) => {  // loop over all tasks
         await getComments(task.id)  // get comments for specific task
           .then((res) => (task.comments = res.data))  // add to comments property
       });
     };

    getAllComments()
    
    setAllTasks(tasks);  // update allTasks with new array including comments
  }, [getComments, allTasks]);
  

Я ожидал allTasks , что теперь у меня будут комментарии из запроса на выборку, т.Е.

 {
 id: 1,
 parent_id: undefined,
 content: "Some content",
 priority: 2,
 labels: ["thing", "other"],
 comments: [{id: 12, content: "comment1"}, {id: 22, content: "comment2"}]
 complete: false,
}
  

Функция рендеринга в соответствии с запросом

 return (
        <div>
            {nestedAllTasks.length !== 0 ? (
              nestedAllTasks.map((task) => {
                return <Task key={task.id} task={task} colours={colours} />;
              })
            ) : (
              <p>Loading active tasks...</p>
            )}
        </div>
      );
  

Компонент задачи

 export default function Task() {
  return (
    <div key={task.id}>  
      <div>{task.content}</div>
        <div>
          {task.comments
          ? task.comments.map((comment) => <div>{comment.content}</div>)
          : null}
        </div>
      </div>
    </div>
  );
}
  

Когда я console.log(allTasks) , я иногда получаю то, что ожидаю, но это никогда не отображается на экране.

Комментарии:

1. Покажите нам свой render()

2. @k-wasilewski, функция рендеринга добавлена в соответствии с запросом.

Ответ №1:

Вы использовали then с await в последнем useEffect. Это неверно. Вы должны сохранить возвращаемое значение await в переменной.

   tasks.map(async (task) => {  // loop over all tasks
         let  res = await getComments(task.id) 
         task.comments = res.data 
       });
     };
  

Комментарии:

1. Внесение этих изменений означает, что я могу консольно регистрировать allTasks и получать массив задач с данными комментариев, но это не отображается на экране! Похоже, что ему нужно сообщить о рендеринге после того, как он каким-то образом получит данные, но я думал, что для этого useEffect и было нужно.