nextjs - 我的钩子不会在值更改时重新渲染

问题描述 投票:0回答:1

我在 page.tsx 文件中使用以下挂钩,然后将数据传递到表中。当我点击一个任务时,我有以下功能

page.tsx “使用客户端”

const { allOpenTasks, getOpenTasks } = useTasks();
  useEffect(() => {
    const fetchTasks = async () => {
      await getOpenTasks(user.id);
    };
    fetchTasks();
  }, []);

useTasks.tsx

export const useTasks = () => {
  const [allOpenTasks, setAllOpenTasks] = useState<any>([]);

  const getOpenTasks = async (userId: any) => {
    try {
      const { data, error } = await supabase
        .from("task")
        .select(
          `
          id,
          is_complete
      `
        )
        .eq("owner_id", userId);

      if (error) {
        throw error;
      }
      if (data) {
        setAllOpenTasks(data);
      }
    } catch (error: any) {
      console.log(error.message);
    }
  };

  const setTaskCompleted = function (taskId: any) {
    const updatedTasks = allOpenTasks.map((task: any) =>
      task.id === taskId ? { ...task, is_complete: !task.is_complete } : task
    );
    setAllOpenTasks([...updatedTasks]);
  };

  return {
    allOpenTasks,
    getOpenTasks,
    setTaskCompleted
  };
};

表.tsx “使用客户端”

  const { setTaskCompleted } = useTasks();
  const clickCompleteTask = async (taskId: any) => {
    try {
      const { error } = await supabase
        .from("task")
        .update({
          is_complete: true,
        })
        .eq("id", taskId);
      if (error) throw new Error();
      setTaskCompleted(taskId);
    } catch (err) {
      console.log(err);
    }
  };

我已经尝试过以下有效的方法。 我可以将其维护在 page.tsx 文件中,并且只使用钩子从 supabase 获取数据,而不是将任务状态保留在钩子内。

我认为如果它位于钩子内部,它看起来会更干净,但它不会在任务对象的状态更改时重新渲染(当其设置为完成时)

我怀疑它是因为当 setTaskCompleted 在开始时初始化时, allOpenTasks 是空的,因为 supabase 还没有设置它。

如果有更好的模式,我也愿意接受。

谢谢!

reactjs next.js usehooks-ts
1个回答
0
投票

你可以尝试一下吗

const setTaskCompleted = function (taskId: any) {
  if (allOpenTasks.length > 0) {
    const updatedTasks = [...allOpenTasks].map((task: any) =>
      task.id === taskId ? { ...task, is_complete: !task.complete } : task
    );
    setAllOpenTasks(updatedTasks);
  } else {
    console.log("Tasks not loaded yet, cannot update completion status.");
  }
};

解决这个问题并确保当 allOpenTasks 中的数据发生变化时重新渲染。

我认为它有两个问题,

  • if (allOpenTasks.length > 0)
    如果supabase返回空,则数据为空,确保在更新之前获取数据我有条件。
  • [...allOpenTasks].map
    为了解决这个问题并确保当
    allOpenTasks
    内的数据发生变化时重新渲染。

无论如何,我认为你的代码总体来说是完美的

© www.soinside.com 2019 - 2024. All rights reserved.