firebase使用_如何使用Firebase和React(Hooks)构建实时聊天室

本文介绍了如何使用Firebase的实时数据库功能和React Hooks构建一个简单的全局聊天室应用。首先通过create-react-app创建React项目,然后设置Firebase。接着展示如何使用基于类的组件实现应用,再过渡到使用React Hooks重构代码,实现状态管理和数据库交互。文章还提到了自定义Hook的概念,以实现组件间的逻辑复用,并提供了相关资源以深入理解React Hooks。
摘要由CSDN通过智能技术生成

firebase使用

by Aswin M Prabhu

由Aswin M Prabhu

If you are into front-end development, I bet you know what react is. It has become the most popular front-end framework and does not appear to be slowing down. Firebase is a back-end service created by Google that enables developers to rapidly iterate on their applications without worrying about run of the mill stuff like authentication, database, storage.

如果你到前端开发,我敢打赌,你知道什么React是。 它已成为最流行的前端框架,并且似乎没有放慢速度。 Firebase是由以下人员创建的后端服务 Google使开发人员能够快速迭代其应用程序,而不必担心认证,数据库和存储等工厂事务的运行。

Firebase has two database options, both of which have awesome real-time capabilities. For example, you can subscribe to changes in a document stored in firebase cloud firestore with the following JavaScript snippet.

Firebase有两个数据库选项,它们都具有出色的实时功能 。 例如,您可以使用以下JavaScript代码段订阅存储在Firebase Cloud Firestore中的文档中的更改。

db.collection("cities").doc("SF")    .onSnapshot(function(doc) {        console.log("Current data: ", doc.data());    });

The callback provided to the onSnapshot() function fires every time the document changes. Local writes from your app will fire it immediately with a feature called latency compensation.

每次文档更改时,都会为onSnapshot()函数提供回调。 应用程序的本地写入将立即使用延迟补偿功能触发它。

React Hooks are an upcoming react feature that let you use state and other react features without writing a class. They’re currently in react v16.7.0-alpha. Building this app is a great way to explore the future of react with react hooks.

React钩 是即将推出的React功能,使您无需编写类即可使用状态和其他React功能。 他们目前在React v16.7.0-alpha中。 构建这个应用程序是探索React的未来的好方法。

The final product will be an IRC like global chatroom app where we first ask the user to enter a nickname. Simple.

最终产品将是类似IRC的全球聊天室应用程序,我们首先要求用户输入一个昵称。 简单。

脚手架 (Scaffolding)

A new react app can easily be created with the official create-react-app cli tool with the following terminal commands (react hooks need react and react-dom v16.7.0-alpha).

可以使用官方的create-react-app cli工具通过以下终端命令轻松创建新的react应用程序(react hooks需要react和react-dom v16.7.0-alpha)。

npm i -g create-react-appcreate-react-app react-firebase-chatroomcd react-firebase-chatroomnpm i -S react@16.7.0-alpha.2 react-dom@16.7.0-alpha.2

The firebase setup is pretty straight forward as well. Create a new project from the firebase console. Setup the firebase real-time database in test mode. Initialize the local project with firebase-tools command. Choose the realtime-database and hosting as the enabled features. Select build as the public directory. Every other option can be left as is.

Firebase的设置也非常简单。 从firebase控制台创建一个新项目 在测试模式下设置firebase实时数据库。 使用firebase-tools初始化本地项目 命令。 选择实时数据库和托管作为已启用的功能。 选择build作为公共目录。 其他所有选项都可以保留。

npm i -g firebase-toolsfirebase-tools initnpm i -S firebase

It might need you to login before you can initialize the repository.

在初始化存储库之前,可能需要先登录。

The database structure will look like the following.

数据库结构如下所示。

使用良好的基于​​旧类的组件构建应用 (Building the app using good old class based components)

React hooks are still an experimental feature and the API might change in the future. So let us first look at how the app can be build with class based components. I went with only the App component because the application logic was simple enough.

React挂钩仍是一项实验性功能,API将来可能会更改。 因此,让我们首先看看如何使用基于类的组件来构建应用程序。 我只使用App组件,因为应用程序逻辑非常简单。

The user will be prompted to join with a nickname and an email if the joined variable is false . It is initially set to false in the constructor .

如果joined变量为false将提示用户加入昵称和电子邮件。 最初在constructor中将其设置为false。

constructor() {    super();    this.state = {      joined: false,      nickname: "",      email: "",      msg: "",      messages: {},    };    this.chatRoom = db.ref().child('chatrooms').child('global');    this.handleNewMessages = snap => {      console.log(snap.val());      if (snap.val()) this.setState({ messages: snap.val() });    };  }
componentDidMount() {    this.chatRoom.on('value', this.handleNewMessages);  }
componentWillUnmount() {    this.chatRoom.off('value', this.handleNewMessages);  }

All the messages are initially fetched from firebase in the componentDidMount life cycle method. The on method on a db ref takes an event type and a callback as arguments. Every time a user sends a new message and updates the database, the handleNewMessages function receives a snapshot of the updated data and updates the state with the new messages. We can unsubscribe from the database updates in the componentWillUnmount life cycle method using the off method on the db ref.

所有消息最初都是使用componentDidMount生命周期方法从firebase中获取的。 db ref上的on方法将事件类型和回调作为参数。 每次用户发送新消息并更新数据库时, handleNewMessages函数都会接收更新数据的快照,并使用新消息更新状态。 我们可以使用db ref上的off方法取消订阅componentWillUnmount生命周期方法中的数据库更新。

A message can be sent by appending the message to the chatroom ref on the database. The push method of the ref generates a unique id for the new entry and appends it to the existing data.

可以通过将消息附加到数据库上的聊天室引用来发送消息。 ref的push方法为新条目生成唯一的ID,并将其附加到现有数据中。

this.chatRoom.push({  sender: this.state.nickname,  msg: this.state.msg,});

The messages are rendered by looping over the messages object.

通过遍历messages对象来呈现messages

{Object.keys(this.state.messages).map(message => {  if(this.state.messages[message]["sender"] === this.state.nickname)    // render the user's messages        else    // render messages from other users})}

The final App component will look like this.

最终的App组件将如下所示。

Find the gist here.

这里找到要点

迁移以响应钩子 (Migrating to react hooks)

The simplest hook is the useState hook. It takes the initial state and returns the state variable and a function that lets you update it. This function acts as a replacement for this.setState . For example the nickname state logic can be modified as follows.

最简单的钩子是useState钩子。 它采用初始状态并返回状态变量和一个使您对其进行更新的函数。 此函数替代this.setState 。 例如,昵称状态逻辑可以如下进行修改。

const [nickname, setNickname] = useState("");const handleNameChange = e => setNickname(e.target.value);...// during render<input placeholder="Nickname" value={nickname} onChange={handleNameChange} />

The next challenge is to find a place for the logic inside the life cycle methods. This is where the useEffect hook comes in. This is where we perform logic that has side effects. It can be thought of as a combination of all the life cycle methods. useEffect can also optionally return a function that is used to clean up (like unsubscribe to an event).

下一个挑战是在生命周期方法中找到逻辑的位置。 这是useEffect钩子出现的地方。这是我们执行具有副作用的逻辑的地方。 可以将其视为所有生命周期方法的组合。 useEffect还可以选择返回用于清除的函数(例如取消订阅事件)。

useEffect(() => {  const handleNewMessages = snap => {    if (snap.val()) setMessages(snap.val());  }  chatRoom.on('value', handleNewMessages);  return () => {    chatRoom.off('value', handleNewMessages);  };});

Subscription and unsubscription were related pieces of logic that were split into different life cycle methods. Now they are put together in a single hook. Using different useEffect hooks for different side effects enables separation of concerns.

订阅和取消订阅是相关的逻辑部分,分为不同的生命周期方法。 现在将它们放在一起。 对不同的副作用使用不同的useEffect挂钩可将关注点分离。

By default, useEffect runs both after the first render and after every update.

默认情况下, useEffect在第一个渲染之后每次更新之后都运行。

One of the major advantages of using hooks is that stateful logic can be reused between components. For example, imagine you want to reuse email input handling and validating logic in multiple components. A custom hook can achieve this as shown below. A custom hook is a function that can call other hooks and starts with “use”. Starting with “use” is not a rule but a very important convention.

使用挂钩的主要优点之一是,状态逻辑可以在组件之间重用。 例如,假设您想在多个组件中重用电子邮件输入处理和验证逻辑。 定制钩子可以实现此目的,如下所示。 自定义钩子是可以调用其他钩子并以“ use”开头的函数。 从“使用”开始不是一个规则,而是一个非常重要的约定。

function useEmail(defaultEmail) {  const [email, setEmail] = useState(defaultEmail);  const [isValidEmail, setValidEmail] = useState(defaultEmail);
function validateEmail(email) {    const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;    return re.test(String(email).toLowerCase());  }
function handleEmailChange(e) {    if (validateEmail(e.target.value)) {      setValidEmail(true);    }    setEmail(e.target.value);  }  return {    email,    handleEmailChange,    isValidEmail  };}

And in your components you can use the custom hook as shown below.

并且在您的组件中,您可以使用自定义钩子,如下所示。

// in your componentsconst { email, handleEmailChange, isValidEmail } = useEmail("")...<input value={email} value={email} onChange={handleEmailChange} />// show error message based on isValidEmail

Custom hooks also make it easier to unit test a piece of logic independent of the components that use the hook.

定制钩子还使对使用该钩子的组件独立的逻辑单元测试变得更容易。

The final App component looks as follows.

最终的App组件如下所示。

Find the gist here.

这里找到要点。

关于钩子还有更多值得阅读的内容 (There’s more to read on hooks)
  1. Motivation behind hooks

    背后的动机

  2. Golden rules of hooks

    钩的黄金法则

  3. Hooks API Reference

    Hooks API参考

  4. Making sense of hooks by Dan Abramov

    Dan Abramov对钩子的理解

Find the final app with bare minimum styling.

查找具有最低限度样式的最终应用

Thanks for reading and happy hacking!

感谢您的阅读和愉快的黑客入侵!

Find me on Twitter and GitHub.

TwitterGitHub上找到我

翻译自: https://www.freecodecamp.org/news/how-to-build-a-real-time-chatroom-with-firebase-and-react-hooks-eb892fa72f1e/

firebase使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值