获取文档函数在React中多次运行

huangapple go评论77阅读模式
英文:

Get doc function running multiple times in React

问题

我正在使用Firebase进行身份验证和存储。我正在使用React中的useContext将我的应用程序包装在身份验证层中。

一旦我从身份验证层获取用户,然后我会调用Firestore来检索用户的详细信息。但是,这个函数一直在循环调用(被多次调用)。

export default function Profile() {
  const { user, loading } = useContext(authContext);
  const [profile, setProfile] = useState({});
  const [dropdownOpen, setDropdownOpen] = useState(false);
  const router = useRouter();

  // 此函数一直在循环调用
  const handleProfile = async () => {
    const userProfileRef = doc(FIREBASE_FIRESTORE, "user", user.uid);
    try {
      const userProfile = await getDoc(userProfileRef);
      setProfile(userProfile.data());
      console.log("SET USER DATA");
    } catch (error) {
      console.log(error);
    }
  };

  if (!user && !loading) {
    router.push("/");
  }

  return (
    <div className="flex flex-col relative">
      {user &&
        !loading &&
        (handleProfile(),
        (
          <button
            onClick={() => setDropdownOpen((prev) => !prev)}
            className="flex items-center gap-2.5 focus:ring-0"
          >
            <Image
              placeholder="blue"
              alt="user profile"
              src={profile.image_URL}
              height={48}
              width={48}
              className="rounded-full bg-gray-400"
            />
            <div className="flex flex-col text-left">
              <p className="font-semibold">{profile.name}</p>
              <p className="text-gray-400 text-sm">{profile.email}</p>
            </div>
            {dropdownOpen ? (
              <FiChevronUp size={"20px"} color={"gray"} />
            ) : (
              <FiChevronDown size={"20px"} color={"gray"} />
            )}
          </button>
        ))}
      <div>{dropdownOpen && <UserDropdown />}</div>
    </div>
  );
}

如何解决这个问题?

英文:

I'm using Firebase for Authentication & Storage. I am using useContext from react to wrap my app in an authentication layer.

Once I get the user from the authentication layer I then make a call to Firestore to retrieve the users details. However, this function is being looped (called multiple times).

export default function Profile() {
const { user, loading } = useContext(authContext);
const [profile, setProfile] = useState({});
const [dropdownOpen, setDropdownOpen] = useState(false);
const router = useRouter();
// THIS FUNCTION IS BEING LOOPED
const handleProfile = async () =&gt; {
const userProfileRef = doc(FIREBASE_FIRESTORE, &quot;user&quot;, user.uid);
try {
const userProfile = await getDoc(userProfileRef);
setProfile(userProfile.data());
console.log(&quot;SET USER DATA&quot;);
} catch (error) {
console.log(error);
}
};
if (!user &amp;&amp; !loading) {
router.push(&quot;/&quot;);
}
return (
&lt;div className=&quot;flex flex-col relative&quot;&gt;
{user &amp;&amp;
!loading &amp;&amp;
(handleProfile(),
(
&lt;button
onClick={() =&gt; setDropdownOpen((prev) =&gt; !prev)}
className=&quot;flex items-center gap-2.5 focus:ring-0&quot;
&gt;
&lt;Image
placeholder=&quot;blue&quot;
alt=&quot;user profile&quot;
src={profile.image_URL}
height={48}
width={48}
className=&quot;rounded-full bg-gray-400&quot;
/&gt;
&lt;div className=&quot;flex flex-col text-left&quot;&gt;
&lt;p className=&quot;font-semibold&quot;&gt;{profile.name}&lt;/p&gt;
&lt;p className=&quot;text-gray-400 text-sm&quot;&gt;{profile.email}&lt;/p&gt;
&lt;/div&gt;
{dropdownOpen ? (
&lt;FiChevronUp size={&quot;20px&quot;} color={&quot;gray&quot;} /&gt;
) : (
&lt;FiChevronDown size={&quot;20px&quot;} color={&quot;gray&quot;} /&gt;
)}
&lt;/button&gt;
))}
&lt;div&gt;{dropdownOpen &amp;&amp; &lt;UserDropdown /&gt;}&lt;/div&gt;
&lt;/div&gt;
);
}

How can I resolve this?

答案1

得分: 1

我建议将 handleProfile 移入 useEffect 中,因为它只是从你的 Firestore 获取数据:

useEffect(() => {
    async function handleProfile() {
      if (user.uid) {
        const userProfileRef = doc(FIREBASE_FIRESTORE, "user", user.uid);
        try {
          const userProfile = await getDoc(userProfileRef);
          setProfile(userProfile.data());
          console.log("设置用户数据");
        } catch (error) {
          console.log(error);
        }
      }
    };

    handleProfile();
  }, [user]);

然后,我还建议在你的 JSX 中移除 handleProfile() 的调用。

如果你正在使用 NextJS,我还建议查看它们关于数据获取的解决方案(根据你的 NextJS 版本会有所不同)。

英文:

I would recommend moving handleProfile into a useEffect as it is just getting data from your firestore:

useEffect(() =&gt; {
async function handleProfile() {
if(user.uid) {
const userProfileRef = doc(FIREBASE_FIRESTORE, &quot;user&quot;, user.uid);
try {
const userProfile = await getDoc(userProfileRef);
setProfile(userProfile.data());
console.log(&quot;SET USER DATA&quot;);
} catch (error) {
console.log(error);
}
}
};
handleProfile();
}, [user]);

I would then also remove the handleProfile() call in your JSX.

If you are using NextJS I would also recommend looking into their solution for data fetching (Will vary depending on your NextJS Version)

huangapple
  • 本文由 发表于 2023年6月22日 16:06:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定