【问题标题】:How to update array with data from an axios fetch request and render using React Hooks如何使用来自 axios 获取请求的数据更新数组并使用 React Hooks 进行渲染
【发布时间】:2020-08-18 16:28:41
【问题描述】:

我从 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并添加cmets,每个评论都需要一个基于任务id的获取请求,我已经封装在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 现在可以从 fetch 请求中获得一个 cmets,即

{
 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) 时,我有时会得到我期望的结果,但这永远不会呈现在屏幕上。

【问题讨论】:

  • 向我们展示您的render()
  • @k-wasilewski,按要求添加了渲染功能。

标签: reactjs axios react-hooks


【解决方案1】:

您在最后一个 useEffect 中使用了 thenawait。这是不正确的。您应该将 await 的返回值保存在一个变量中。

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

【讨论】:

  • 进行此更改意味着我可以控制台登录allTasks 并获取带有评论数据的任务数组,但这不会在屏幕上呈现!这就像它需要被告知在以某种方式获取数据后进行渲染,但我认为这就是 useEffect 的用途。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 2020-01-15
  • 2020-04-20
  • 2020-04-14
  • 2019-11-15
相关资源
最近更新 更多