我无法在Nextjs中正确使用useState

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

发送第一个请求时,isVoting 将设置为“true”。在这种情况下,在 isVoting 设置为“false”之前,不应允许发送另一个请求。但不知何故,当我尝试快速多次点击否决时, isVoting 仍然是“假”。 并且投反对票请求发送了两次,这是不正确的。我该如何解决这个问题?

"use client";
import { downvoteAnswer } from "@/lib/actions/answer.action";
import Image from "next/image";
import { usePathname, useRouter } from "next/navigation";
import { useState } from "react";

interface Props {
  type: string;
  itemId: string;
  userId: string;
  upvotes: number;
  hasupVoted: boolean;
  downvotes: number;
  hasdownVoted: boolean;
  authorId: string;
  hasSaved?: boolean;
}

const Votes = ({
  type,
  itemId,
  userId,
  upvotes,
  hasupVoted,
  authorId,
  downvotes,
  hasdownVoted,
  hasSaved,
}: Props) => {
  const [isVoting, setIsVoting] = useState(false);
  const pathname = usePathname();
  const router = useRouter();

  const handleVote = async (action: string) => {
    console.log("isVoting:", isVoting);
    if (isVoting) {
      console.log("Request denied");
      return;
    }

      setIsVoting(true);
      await downvoteAnswer({
        answerId: JSON.parse(itemId),
        userId: JSON.parse(userId),
        hasupVoted,
        hasdownVoted,
        path: pathname,
      });
      setIsVoting(false);
    }
  };


  return (
    <div className="flex gap-5">
        <div className="flex-center gap-1.5">
          <Image
            src={
              hasdownVoted
                ? "/assets/icons/downvoted.svg"
                : "/assets/icons/downvote.svg"
            }
            width={18}
            height={18}
            alt="downvote"
            className="cursor-pointer"
            onClick={() => handleVote("downvote")}
          />
        </div>
    </div>
  );
};

export default Votes;
javascript reactjs next.js react-hooks nextjs14
1个回答
0
投票

React 状态更新是异步的,并且跨渲染更新 isVoting 状态可能会有延迟。

就像 @hairyhandkerchief23 所说,你应该使用带有布尔值的 useRef() 。

你可以这样尝试:

const isVotingRef = useRef(false);

const handleVote = async (action: string) => {
  console.log("isVoting:", isVotingRef.current); 
  if (isVotingRef.current) {  // Use ref's current value
    console.log("Request denied");
    return;
  }

  isVotingRef.current = true; // this prevents multiple calling
  try {
    await downvoteAnswer({
      answerId: JSON.parse(itemId),
      userId: JSON.parse(userId),
      hasupVoted,
      hasdownVoted,
      path: pathname,
    });
  } catch (error) {
    console.error("Error in voting:", error);
  } finally {
    isVotingRef.current = false; // reset after finished
  }
};

希望这有帮助

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