Firebase 和 React Hooks(useState 和 useEffect)
Posted
技术标签:
【中文标题】Firebase 和 React Hooks(useState 和 useEffect)【英文标题】:Firebase and React Hooks (useState & useEffect) 【发布时间】:2020-03-23 16:20:35 【问题描述】:我有一个基本的 react hooks 用法,但它似乎失败了。
错误
错误:无效的挂钩调用。
代码
function GetUserDisplayName(userId)
const [displayName, setDisplayName] = useState("Jane Doe");
db.collection("users")
.doc(userId)
.get()
.then(doc =>
setDisplayName(doc.data().displayName);
);
return displayName;
注意,即使没有 db 调用,它也无法简单地返回默认的 displayName。
【问题讨论】:
将代码块放入try
catch
并检查错误?该功能是功能组件内部的功能吗?为什么useState
钩子在那个函数里面?
您打算调用 firebase onMount 还是响应用户操作(如按钮单击)?下面techGuru的回答针对前者,我的回答针对后者。
我试图用用户名填充 dom - 它存储在用户集合中。这不需要用户操作。
【参考方案1】:
您发布的是一种方法,而不是自定义挂钩。按照惯例,所有挂钩都以“use”一词开头。如果要在挂钩中触发效果,则必须在自定义挂钩中使用 useEffect 挂钩。
import React, useState, useEffect from 'react';
function useDisplayName(userId)
const [displayName, setDisplayName] = useState("Jane Doe");
useEffect(() =>
db.collection("users")
.doc(userId)
.get()
.then(doc =>
doc.exists &&
doc.data().displayName &&
setDisplayName(doc.data().displayName);
);
, []);
return displayName
下面的钩子将在初始化时运行,如componentDidMount,如果你想改变它,你可以在效果钩子的第二个参数中添加依赖项到数组中。 More info on that here
【讨论】:
您假设GetUserDisplayName
是一个功能组件?它可以是functional
组件内的method
吗?
钩子只能在功能组件中使用,不能在类组件中使用钩子。在类组件中,您可以使用常规的生命周期方法。
我知道,但我要说的是问题中提到的功能可以是功能组件内部的方法吗?不是主要组件
功能组件就是一个功能。为什么要将它包装在一个多余的额外 GetUserDisplayName
函数方法中?只需在功能组件中的 useEffect 挂钩中调用 firebase。
@JoshPittman 好像声明了“取消订阅”,但从未使用过?【参考方案2】:
我假设上面提供的函数是函数 component
中的 method
。
useState
应该在组件中的方法之外。
const yourComponent = () =>
const [displayName, setDisplayName] = useState("Jane Doe");
const GetUserDisplayName = (userId) =>
db.collection("users")
.doc(userId)
.get()
.then(doc =>
setDisplayName(doc.data().displayName);
);
return displayName;
return <p> INSERT JSX HERE</p>
【讨论】:
如果您不想使用任何生命周期方法,这个答案是完美的。例如,如果您想获取数据以响应按钮单击或其他操作。我假设问题是在生命周期方法的上下文中,否则根本不需要使用钩子。这只是一个普通的函数方法。 感谢您的澄清,我对 Firebase 不太熟悉,所以只是用谷歌搜索了一下,我完全同意你的看法!!!【参考方案3】:尝试使用useEffect
钩子
import React, useState, useEffect from "react";
import ReactDOM from "react-dom";
function useDisplayName(userId)
const [displayName, setDisplayName] = useState("Jane Doe");
useEffect(() =>
db.collection("users")
.doc(userId)
.get()
.then(doc =>
setDisplayName(doc.data().displayName);
);
, [userId]);
return displayName;
function App()
const displayName = useDisplayName("Your ID");
return <div>displayName</div>;
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
【讨论】:
以上是关于Firebase 和 React Hooks(useState 和 useEffect)的主要内容,如果未能解决你的问题,请参考以下文章
React Hooks 不适用于 Firebase Cloud Functions 错误:不变违规:无效的钩子调用
React Hooks + Firebase Firestore onSnapshot - 正确使用带有反应钩子的 Firestore 监听器