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

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

Get doc function running multiple times in React

问题

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

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

  1. export default function Profile() {
  2. const { user, loading } = useContext(authContext);
  3. const [profile, setProfile] = useState({});
  4. const [dropdownOpen, setDropdownOpen] = useState(false);
  5. const router = useRouter();
  6. // 此函数一直在循环调用
  7. const handleProfile = async () => {
  8. const userProfileRef = doc(FIREBASE_FIRESTORE, "user", user.uid);
  9. try {
  10. const userProfile = await getDoc(userProfileRef);
  11. setProfile(userProfile.data());
  12. console.log("SET USER DATA");
  13. } catch (error) {
  14. console.log(error);
  15. }
  16. };
  17. if (!user && !loading) {
  18. router.push("/");
  19. }
  20. return (
  21. <div className="flex flex-col relative">
  22. {user &&
  23. !loading &&
  24. (handleProfile(),
  25. (
  26. <button
  27. onClick={() => setDropdownOpen((prev) => !prev)}
  28. className="flex items-center gap-2.5 focus:ring-0"
  29. >
  30. <Image
  31. placeholder="blue"
  32. alt="user profile"
  33. src={profile.image_URL}
  34. height={48}
  35. width={48}
  36. className="rounded-full bg-gray-400"
  37. />
  38. <div className="flex flex-col text-left">
  39. <p className="font-semibold">{profile.name}</p>
  40. <p className="text-gray-400 text-sm">{profile.email}</p>
  41. </div>
  42. {dropdownOpen ? (
  43. <FiChevronUp size={"20px"} color={"gray"} />
  44. ) : (
  45. <FiChevronDown size={"20px"} color={"gray"} />
  46. )}
  47. </button>
  48. ))}
  49. <div>{dropdownOpen && <UserDropdown />}</div>
  50. </div>
  51. );
  52. }

如何解决这个问题?

英文:

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).

  1. export default function Profile() {
  2. const { user, loading } = useContext(authContext);
  3. const [profile, setProfile] = useState({});
  4. const [dropdownOpen, setDropdownOpen] = useState(false);
  5. const router = useRouter();
  6. // THIS FUNCTION IS BEING LOOPED
  7. const handleProfile = async () =&gt; {
  8. const userProfileRef = doc(FIREBASE_FIRESTORE, &quot;user&quot;, user.uid);
  9. try {
  10. const userProfile = await getDoc(userProfileRef);
  11. setProfile(userProfile.data());
  12. console.log(&quot;SET USER DATA&quot;);
  13. } catch (error) {
  14. console.log(error);
  15. }
  16. };
  17. if (!user &amp;&amp; !loading) {
  18. router.push(&quot;/&quot;);
  19. }
  20. return (
  21. &lt;div className=&quot;flex flex-col relative&quot;&gt;
  22. {user &amp;&amp;
  23. !loading &amp;&amp;
  24. (handleProfile(),
  25. (
  26. &lt;button
  27. onClick={() =&gt; setDropdownOpen((prev) =&gt; !prev)}
  28. className=&quot;flex items-center gap-2.5 focus:ring-0&quot;
  29. &gt;
  30. &lt;Image
  31. placeholder=&quot;blue&quot;
  32. alt=&quot;user profile&quot;
  33. src={profile.image_URL}
  34. height={48}
  35. width={48}
  36. className=&quot;rounded-full bg-gray-400&quot;
  37. /&gt;
  38. &lt;div className=&quot;flex flex-col text-left&quot;&gt;
  39. &lt;p className=&quot;font-semibold&quot;&gt;{profile.name}&lt;/p&gt;
  40. &lt;p className=&quot;text-gray-400 text-sm&quot;&gt;{profile.email}&lt;/p&gt;
  41. &lt;/div&gt;
  42. {dropdownOpen ? (
  43. &lt;FiChevronUp size={&quot;20px&quot;} color={&quot;gray&quot;} /&gt;
  44. ) : (
  45. &lt;FiChevronDown size={&quot;20px&quot;} color={&quot;gray&quot;} /&gt;
  46. )}
  47. &lt;/button&gt;
  48. ))}
  49. &lt;div&gt;{dropdownOpen &amp;&amp; &lt;UserDropdown /&gt;}&lt;/div&gt;
  50. &lt;/div&gt;
  51. );
  52. }

How can I resolve this?

答案1

得分: 1

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

  1. useEffect(() => {
  2. async function handleProfile() {
  3. if (user.uid) {
  4. const userProfileRef = doc(FIREBASE_FIRESTORE, "user", user.uid);
  5. try {
  6. const userProfile = await getDoc(userProfileRef);
  7. setProfile(userProfile.data());
  8. console.log("设置用户数据");
  9. } catch (error) {
  10. console.log(error);
  11. }
  12. }
  13. };
  14. handleProfile();
  15. }, [user]);

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

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

英文:

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

  1. useEffect(() =&gt; {
  2. async function handleProfile() {
  3. if(user.uid) {
  4. const userProfileRef = doc(FIREBASE_FIRESTORE, &quot;user&quot;, user.uid);
  5. try {
  6. const userProfile = await getDoc(userProfileRef);
  7. setProfile(userProfile.data());
  8. console.log(&quot;SET USER DATA&quot;);
  9. } catch (error) {
  10. console.log(error);
  11. }
  12. }
  13. };
  14. handleProfile();
  15. }, [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:

确定