发布于 2026-01-06 6 阅读
0

使用 Firebase 和 React Hooks DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

将 Firebase 与 React Hooks 结合使用

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

本教程演示如何在 React 应用中使用Hooks,以便更好地集成 Firebase 身份验证和 Firestore 数据获取。在开始之前,建议您对Hooks、Firebase身份验证Firestore有一定的了解。教程最后,我们将构建示例应用Julienne.app中的一些 Hooks

监控身份验证

结合使用 Hooks 和Context,可以轻松地在 React 应用的任何位置访问用户会话。我们可以将用户会话存储在 Context 中,并将该 Context 传递给子组件。这些子组件随后可以使用 Hooks 来访问会话对象。

首先,构建我们的背景。

const userContext = React.createContext({
  user: null,
})

我们为上下文提供的默认值包含一个空的会话对象。当我们使用 Firebase 监控会话更改时,此值将会改变。

接下来,我们将创建一个钩子,以便访问我们的上下文。

export const useSession = () => {
  const { user } = useContext(userContext)
  return user
}

最后,我们来创建一个钩子来监控 Firebase 身份验证状态。这个钩子会创建一个状态,该状态使用useState回调函数来判断用户会话是否已存在。回调函数的作用在于,它允许组件仅在首次挂载时才初始化状态值。

接下来,我们使用一个effect监控身份验证更改的函数。当您使用 Firebase 提供的众多登录方法之一触发登录(或注销)时,该onChange函数将使用当前的身份验证状态进行调用。

最后,我们返回身份验证状态。

export const useAuth = () => {
  const [state, setState] = React.useState(() => { const user = firebase.auth().currentUser return { initializing: !user, user, } })
  function onChange(user) {
    setState({ initializing: false, user })
  }

  React.useEffect(() => {
    // listen for auth state changes
    const unsubscribe = firebase.auth().onAuthStateChanged(onChange)
    // unsubscribe to the listener when unmounting
    return () => unsubscribe()
  }, [])

  return state
}

然后,我们可以在应用程序的顶层使用此钩子,并使用我们的上下文提供程序将用户会话提供给子组件。

function App() {
  const { initializing, user } = useAuth()
  if (initializing) {
    return <div>Loading</div>
  }

  return (
    <userContext.Provider value={{ user }}> <UserProfile /> </userContext.Provider> )
}

最后,在子组件中,我们可以使用useSession钩子来访问用户会话。

function UserProfile() {
  const { user } = useSession() return <div>Hello, {user.displayName}</div>
}

实际上,登录或注销完全不需要使用钩子函数。只需在事件处理程序中调用firebase.auth().signOut()各种登录方法即可。

获取文档

使用 Firestore 时,Hooks 可以用来监控单个文档查询。在这个例子中,我们希望在收到 `<recipe>` 参数时获取一个菜谱id。我们需要为组件提供 ` <recipe>` errorloading`<recipe>` 和recipe`<state>` 参数。

function useRecipe(id) {
  // initialize our default state
  const [error, setError] = React.useState(false) const [loading, setLoading] = React.useState(true) const [recipe, setRecipe] = React.useState(null)
  // when the id attribute changes (including mount)
  // subscribe to the recipe document and update
  // our state when it changes.
  useEffect(
    () => {
      const unsubscribe = firebase.firestore().collection('recipes') .doc(id).onSnapshot( doc => { setLoading(false) setRecipe(doc) }, err => { setError(err) } )
      // returning the unsubscribe function will ensure that
      // we unsubscribe from document changes when our id
      // changes to a different value.
      return () => unsubscribe()
    },
    [id]
  )

  return {
    error,
    loading,
    recipe,
  }
}

获取集合

获取集合的过程非常相似,但我们订阅的是文档集合。

function useIngredients(id) {
  const [error, setError] = React.useState(false)
  const [loading, setLoading] = React.useState(true)
  const [ingredients, setIngredients] = React.useState([])

  useEffect(
    () => {
      const unsubscribe = firebase
        .firestore()
        .collection('recipes')
        .doc(id)
        .collection('ingredients') .onSnapshot( snapshot => { const ingredients = [] snapshot.forEach(doc => { ingredients.push(doc) }) setLoading(false) setIngredients(ingredients) }, err => { setError(err) } )

      return () => unsubscribe()
    },
    [id]
  )

  return {
    error,
    loading,
    ingredients,
  }
}

如果你计划在整个应用程序中使用 Firebase Hooks,我建议你了解一下react-firebase-hooks。它提供了一些有用的辅助函数,使我们能够复用上面编写的部分逻辑。

如需查看使用 Firebase、React 和 Typescript 构建的完整应用程序示例,请查看Julienne

(本文发布在我的博客 benmcmahen.com 上。点击此处即可在线阅读。)

文章来源:https://dev.to/bmcmahen/using-firebase-with-react-hooks-21ap