在10分钟内学习构建React聊天应用-React JS教程

In this article, I’ll show you the easiest way possible to create a chat application using React.js. It’ll be done entirely without server-side code, as we’ll let the Chatkit API handle the back-end.

在本文中,我将向您展示使用React.js创建聊天应用程序的最简单方法。 完全无需服务器端代码即可完成,因为我们让Chatkit API处理后端。

I’m assuming that you know basic JavaScript and that you’ve encountered a little bit of React.js before. Other than that, there are no prerequisites.

我假设您了解基本JavaScript,并且您之前已经遇到过React.js的一些知识。 除此之外,没有任何先决条件。

Note: I’ve also created a free full-length course on how to create a React.js chat app here:

注意:我还创建了一个免费的全长课程,内容涉及如何在此处创建React.js聊天应用程序:

If you follow along with this tutorial you’ll end up with your very own chat application at the end, which you then can build further upon if you’d like to.

如果按照本教程进行操作,最后将得到一个自己的聊天应用程序,如果需要,您可以在该应用程序的基础上进一步进行开发。

Let’s get started!

让我们开始吧!

步骤1:将UI分解为组件 (Step 1: Breaking the UI into components)

React is built around components, so the first thing you want to do when creating an app is to break its UI into components.

React是围绕组件构建的,因此创建应用程序时,您要做的第一件事就是将其UI分解为组件。

Let’s start by drawing a rectangle around the entire app. This is your root component and the common ancestor for all other components. Let’s call it App:

让我们从围绕整个应用程序绘制一个矩形开始。 这是您的根本组成部分,也是所有其他组成部分的共同祖先。 我们称它为App

Once you’ve defined your root component, you need to ask yourself the following question:

定义根组件后,需要问自己以下问题:

Which direct children does this component have?

该组件有哪些直属子代?

In our case, it makes sense to give it three child components, which we’ll call the following:

在我们的例子中,给它三个子组件是有意义的,我们将其称为:

  • Title

    Title

  • MessagesList

    MessagesList

  • SendMessageForm

    SendMessageForm

Let’s draw a rectangle for each of these:

让我们为每个矩形绘制一个矩形:

This gives us a nice overview of the different components and the architecture behind our app.

这使我们可以很好地了解应用程序背后的不同组件和体系结构。

We could have continued asking ourselves which children these components again have. Thus we could have broken the UI into even more components, for example through turning each of the messages into their own components. However, we’ll stop here for the sake of simplicity.

我们本来可以继续问自己,这些组成部分又是哪些孩子。 因此,我们可以将UI分解为更多的组件,例如通过将每条消息转换为它们自己的组件。 但是,为了简单起见,我们将在这里停止。

步骤2:设置代码库 (Step 2: Setting up the codebase)

Now we’ll need to setup our repository. We’ll use the simplest structure possible: an *index.html *file with links to a JavaScript file and a stylesheet. We’re also importing the Chatkit SDK and Babel, which is used to transform our JSX:

现在,我们需要设置我们的存储库。 我们将使用最简单的结构:* index.html *文件,其中包含指向JavaScript文件和样式表的链接。 我们还导入了Chatkit SDK和Babel,用于转换我们的JSX:

Here’s a Scrimba playground with the final code for the tutorial. I’d recommend you to open it up in a new tab and play around with it whenever you feel confused.

这是一个Scrimba游乐场 ,其中包含本教程的最终代码。 我建议您在新标签页中打开它,并在感到困惑时使用它。

Alternatively, you can download the Scrimba project as a .zip file and run a simple server to get it up and running locally.

另外,您可以将Scrimba项目下载为.zip文件,然后运行简单的服务器以使其在本地运行。

步骤3:创建根组件 (Step 3: Creating the root component)

With the repository in place, we’re able to start writing some React code, which we’ll do inside the *index.js *file.

有了存储库之后,我们就可以开始编写一些React代码,我们将在* index.js *文件中进行操作。

Let’s start with the main component, App. This will be our only “smart” component, as it’ll handle the data and the connection with the API. Here’s the basic setup for it (before we’ve added any logic):

让我们从主要组件App 。 这将是我们唯一的“智能”组件,因为它将处理数据以及与API的连接。 这是它的基本设置(在我们添加任何逻辑之前):

class App extends React.Component {
      
      render() {
        return (
          <div className="app">
            <Title />
            <MessageList />
            <SendMessageForm />
         </div>
        )
      }
    }

As you can see, it simply renders out three children: the <Title>,<MessageList>, and the <SendMessageForm> components.

如您所见,它仅呈现了三个子项: <Title><MessageList><SendMessageForm>组件。

We’re going to make it a bit more complex though, as the chat messages will need to be stored inside the state of this App component. This will enable us to access the messages through this.state.messages, and thus pass them around to other components.

不过,我们将使其变得更加复杂,因为聊天消息将需要存储在此App组件的状态内。 这将使我们能够通过this.state.messages访问消息,并将它们传递给其他组件。

We’ll begin with using dummy data so that we can understand the data flow of the app. Then we’ll swap this out with real data from the Chatkit API later on.

我们将从使用伪数据开始,以便我们可以了解应用程序的数据流。 然后,我们稍后将其与来自Chatkit API的真实数据交换出去。

Let’s create a DUMMY_DATA variable:

让我们创建一个DUMMY_DATA变量:

const DUMMY_DATA = [
      {
        senderId: "perborgen",
        text: "who'll win?"
      },
      {
        senderId: "janedoe",
        text: "who'll win?"
      }
    ]

Then we’ll add this data to the state of App and pass it down to the MessageList component as a prop.

然后,我们将该数据添加到App的状态,并将其作为道具传递给MessageList组件。

class App extends React.Component {
      
      constructor() {
        super()
        this.state = {
           messages: DUMMY_DATA
        }
      }
      
      render() {
        return (
          <div className="app">
            <MessageList messages={this.state.messages}/>
            <SendMessageForm />
         </div>
        )
      }
    }

Here, we’re initializing the state in the constructor and we’re also passing this.state.messages down to MessageList.

在这里,我们正在初始化constructor函数中的状态,还将this.state.messages传递给MessageList

Note that we’re calling super() in the constructor. You must do that if you want to create a stateful component.

请注意,我们在构造函数中调用了super() 。 如果要创建有状态组件,则必须执行此操作。

步骤4:呈现伪消息 (Step 4: Rendering dummy messages)

Let’s see how we can render these messages out in the MessageList component. Here’s how it looks:

让我们看看如何在MessageList组件中呈现这些消息。 外观如下:

class MessageList extends React.Component {
      render() {
        return (
          <ul className="message-list">                 
            {this.props.messages.map(message => {
              return (
               <li key={message.id}>
                 <div>
                   {message.senderId}
                 </div>
                 <div>
                   {message.text}
                 </div>
               </li>
             )
           })}
         </ul>
        )
      }
    }

This is a so-called stupid component. It takes one prop, messages, which contains an array of objects. And then we’re simply rendering out the text and senderId properties from the objects.

这是所谓的愚蠢成分。 它需要一个props, messages ,其中包含一组对象。 然后,我们只是从对象中渲染textsenderId属性。

With our dummy data flowing into this component, it will render the following:

随着我们的虚拟数据流入该组件,它将呈现以下内容:

So now we have the basic structure for our app, and we’re also able to render out messages. Great job!

因此,现在我们有了应用程序的基本结构,并且还能够呈现消息。 很好!

Now let’s replace our dummy data with actual messages from a chat room!

现在,让我们用来自聊天室的实际消息替换我们的虚拟数据!

步骤5:从Chatkit中获取API密钥 (Step 5: Fetching API-keys from Chatkit)

In order to get fetch messages, we’ll need to connect with the Chatkit API. And to do so, we need to obtain API keys.

为了获取消息,我们需要连接Chatkit API。 为此,我们需要获取API密钥。

At this point, I want to encourage you to follow my steps so that you can get your own chat application up and running. You can use my Scrimba playground in order to test your own API keys.

在这一点上,我想鼓励您按照我的步骤进行操作,以便您可以启动并运行自己的聊天应用程序。 您可以使用我的Scrimba游乐场来测试您自己的API密钥。

Start by creating a free account here. Once you’ve done that you’ll see your dashboard. This is where you create new Chatkit instances. Create one and give it whatever name you want:

首先在这里创建一个免费帐户 。 完成后,您将看到仪表板。 在这里创建新的Chatkit实例。 创建一个,并给它任何您想要的名称:

Then you’ll be navigated to your newly created instance. Here you’ll need to copy four values:

然后,您将导航到新创建的实例。 在这里,您需要复制四个值:

  • Instance Locator

    实例定位器
  • Test Token Provider

    测试令牌提供者
  • Room id

    房间编号
  • Username

    用户名

We’ll start with the Instance Locator:

我们将从实例定位器开始:

You can copy using the icon on the right side of the Instance Locator.

您可以使用“实例定位器”右侧的图标进行复制。

And if you scroll a bit down you’ll find the Test Token Provider:

如果向下滚动,您会发现Test Token Provider

The next step is to create a User* *and a Room, which is done on the same page. Note that you’ll have to create a user first, and then you’ll be able to create a room, which again gives you access to the room identifier.

下一步是创建User * *和Room ,在同一页面上完成。 请注意,您必须首先创建一个用户,然后你就可以创建房间,这又使您可以访问到房间标识。

So now you’ve found your four identifiers. Well done!

现在,您已经找到了四个标识符。 做得好!

However, before we head back to the codebase, I want you to manually send a message from the Chatkit dashboard as well, as this will help us in the next chapter.

但是,在回到代码库之前,我希望您也从Chatkit仪表板手动发送消息,因为这将在下一章中为我们提供帮助。

Here’s how to do that:

这样做的方法如下:

This is so that we actually have a message to render out in the next step.

这样一来,我们实际上就有一条消息要在下一步中呈现。

步骤6:呈现真实的聊天消息 (Step 6: Rendering real chat messages)

Now let’s head back to our index.js file and store these four identifiers as variables at the top of our file.

现在,让我们回到index.js文件,并将这四个标识符作为变量存储在文件顶部。

Here are mine, but I’d encourage you to create your own:

这是我的,但我鼓励您创建自己的:

const instanceLocator = "v1:us1:dfaf1e22-2d33-45c9-b4f8-31f634621d24"

    const testToken = "https://us1.pusherplatform.io/services/chatkit_token_provider/v1/dfaf1e22-2d33-45c9-b4f8-31f634621d24/token"

    const username = "perborgen"

    const roomId = 9796712

And with that in place, we’re finally ready to connect with Chatkit. This will happen in the App component, and more specifically in the componentDidMount method. That’s the method you should use when connecting React.js components to API’s.

有了这些,我们终于准备好与Chatkit连接。 这将在App组件中发生,更具体地说在componentDidMount方法中发生。 那就是将React.js组件连接到API时应该使用的方法。

First we’ll create a chatManager:

首先,我们将创建一个chatManager

componentDidMount() {
      const chatManager = new Chatkit.ChatManager({
        instanceLocator: instanceLocator,
        userId: userId,
        tokenProvider: new Chatkit.TokenProvider({
          url: testToken
        })
     })

… and then we’ll dochatManager.connect() to connect with the API:

…然后我们将做chatManager.connect()与API连接:

chatManager.connect().then(currentUser => {
          currentUser.subscribeToRoom({
          roomId: roomId,
          hooks: {
            onNewMessage: message => {
              this.setState({
                messages: [...this.state.messages, message]
              })
            }
          }
        })
      })
    }

This gives us access to the currentUser object, which is the interface for interacting with the API.

这使我们可以访问currentUser对象,该对象是与API进行交互的接口。

Note: As we’ll need to usecurrentUser later on, well store it on the instance by doing this.currentUser = ``currentUser.

注意:由于稍后需要使用currentUser ,因此可以通过执行this.currentUser = ``currentUser将其存储在实例中。

Then, we’re calling currentUser.subscribeToRoom() and pass it our roomId and an onNewMessage hook.

然后,我们调用currentUser.subscribeToRoom()并将其传递给我们的roomIdonNewMessage挂钩。

The onNewMessage hook is triggered every time a new message is broadcast to the chat room. So every time it happens, we’ll simply add the new message at the end of this.state.messages.

每当有新消息广播到聊天室时,都会触发onNewMessage挂钩。 因此,每次发生时,我们只需在this.state.messages的末尾添加新消息this.state.messages

This results in the app fetching data from the API and then rendering it out on the page.

这导致应用程序从API提取数据,然后将其呈现在页面上。

This is awesome, as we now have the skeleton for our client-server connection.

太棒了,因为我们现在有了客户端-服务器连接的框架。

Woohoo!

hoo!

步骤7:处理用户输入 (Step 7: Handling user input)

The next thing we’ll need to create is the SendMessageForm component. This will be a so-called controlled component, meaning the component controls what’s being rendered in the input field via its state.

接下来需要创建的是SendMessageForm组件。 这将是所谓的受控组件 ,这意味着该组件通过其状态控制在输入字段中呈现的内容。

Take a look at the render() method, and pay special attention to the lines I’ve highlighted:

看一下render()方法,并特别注意我突出显示的行:

class SendMessageForm extends React.Component {
      render() {
        return (
          <form
            className="send-message-form">
            <input
              onChange={this.handleChange}
              value={this.state.message}
              placeholder="Type your message and hit ENTER"
              type="text" />
          </form>
        )
      }
    }

We’re doing two things:

我们正在做两件事:

  1. Listening for user inputs with the onChange event listener, so that we can

    使用onChange事件侦听器侦听用户输入,以便我们可以

    trigger the

    触发

    handleChange method

    handleChange方法

  2. Setting the value of the input field explicitly using this.state.message

    使用this.state.message显式设置输入字段的value

The connection between these two steps is found inside the handleChange method. It simply updates the state to whatever the user types into the input field:

这两个步骤之间的联系可以在handleChange方法中找到。 它只是将状态更新为用户在输入字段中键入的内容:

handleChange(e) {
      this.setState({
        message: e.target.value
      })
    }

This triggers a re-render, and since the input field is set explicitly from the state using value={this.state.message}, the input field will be updated.

这将触发重新渲染,并且由于使用value={this.state.message}从状态显式设置了输入字段,因此将更新输入字段。

So even though the app feels instant for the user when they type something into the input field, the data actually goes via the state before React updates the UI.

因此,即使应用程序让用户在输入字段中键入内容时感到立即, 但数据实际上是通过状态在React更新UI之前经过的。

To wrap up this feature, we need to give the component a constructor. In it, we’ll both initialize the state and bind this in the handleChange method:

要包装此功能,我们需要为组件提供一个constructor 。 在这里面,我们俩初始化状态,并结合thishandleChange方法:

constructor() {
        super()
        this.state = {
           message: ''
        }
        this.handleChange = this.handleChange.bind(this)
    }

We need to bind the handleChangemethod so that we’ll have access to the this keyword inside of it. That’s how JavaScript works: the this keyword is by default undefined inside the body of a function.

我们需要绑定handleChange方法,以便可以访问其中的this关键字。 这就是JavaScript的工作方式:缺省情况下, this关键字在函数体内未定义

步骤8:发送消息 (Step 8: Sending messages)

Our SendMessageForm component is almost finished, but we also need to take care of the form submission. We need fetch the messages and send them off!

我们的SendMessageForm组件快要完成了,但是我们还需要注意表单提交。 我们需要获取消息并发送出去!

To do this we’ll hook a handleSubmit even handler up with the onSubmit event listener in the <form>.

为此,我们将使用<form>onSubmit事件侦听器将handleSubmit甚至处理程序连接起来。

render() {
        return (
          <form
            onSubmit={this.handleSubmit}
            className="send-message-form">
            <input
              onChange={this.handleChange}
              value={this.state.message}
              placeholder="Type your message and hit ENTER"
              type="text" />
        </form>
        )
      }

As we have the value of the input field stored in this.state.message, it’s actually pretty easy to pass the correct data along with the submission. We’llsimply do:

由于我们将输入字段的值存储在this.state.message ,因此很容易将正确的数据与提交一起传递。 我们将简单地做:

handleSubmit(e) {
      e.preventDefault()
      this.props.sendMessage(this.state.message)
      this.setState({
        message: ''
      })
    }

Here, we’re calling the sendMessage prop and passing in this.state.message as a parameter. You might be a little confused by this, as we haven’t created the sendMessage method yet. However, we’ll do that in the next section, as that method lives inside the App component. So don’t worry!

在这里,我们调用sendMessage this.state.message ,并将this.state.message作为参数传递。 您可能对此有些困惑,因为我们尚未创建sendMessage方法。 但是,由于该方法位于App组件内部,因此我们将在下一部分中进行说明。 所以不用担心!

Secondly, we’re clearing out the input field by setting this.state.message to an empty string.

其次,我们通过将this.state.message设置为空字符串来清除输入字段。

Here’s the entire SendMessageForm component. Notice that we’ve also bound this to the handleSubmit method:

这是整个SendMessageForm组件。 请注意,我们也必将thishandleSubmit方法:

class SendMessageForm extends React.Component {
      constructor() {
        super()
        this.state = {
          message: ''
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
      }

      handleChange(e) {
        this.setState({
          message: e.target.value
        })
      }

      handleSubmit(e) {
        e.preventDefault()
        this.props.sendMessage(this.state.message)
        this.setState({
          message: ''
        })
      }

      render() {
        return (
          <form
            onSubmit={this.handleSubmit}
            className="send-message-form">
            <input
              onChange={this.handleChange}
              value={this.state.message}
              placeholder="Type your message and hit ENTER"
              type="text" />
          </form>
        )
      }
    }

步骤9:将消息发送到Chatkit (Step 9: Sending the messages to Chatkit)

We’re now ready so send the messages off to Chatkit. That’s done up in the App component, where we’ll create a method called this.sendMessage:

现在我们已经准备就绪,因此可以将消息发送给Chatkit。 这在App组件中完成,我们将在其中创建一个名为this.sendMessage的方法:

sendMessage(text) {
      this.currentUser.sendMessage({
        text: text,
        roomId: roomId
      })
    }

It takes one parameter (the text) and it simply calls this.currentUser.sendMessage().

它采用一个参数(文本),并且仅调用this.currentUser.sendMessage()

The final step is to pass this down to the <SendMessageForm> component as a prop:

最后一步是将其作为道具传递给<SendMessageForm>组件:

/* App component */
      
    render() {
      return (
        <div className="app">
          <Title />
          <MessageList messages={this.state.messages} />
          <SendMessageForm sendMessage={this.sendMessage} />
      )
    }

And with that, we’ve passed down the handler so that SendMessageForm can invoke it when the form is submitted.

这样,我们就向下传递了处理程序,以便在提交表单时, SendMessageForm可以调用它。

步骤10:创建标题组件 (Step 10: Creating the Title component)

To finish up, let’s also create the Title component. It’s just a simple functional component, meaning a function which returns a JSX expression.

最后,我们还创建Title组件。 它只是一个简单的功能组件,意味着一个返回JSX表达式的函数。

function Title() {
      return <p class="title">My awesome chat app</p>
    }

It’s a good practice to use functional components, as they have more constraints than class components, which makes them less prone to bugs.

使用功能性组件是一个好习惯,因为它们比类组件具有更多的约束,这使得它们不易出现错误。

结果 (The result)

And with that in place you have your own chat application which you can use to chat with your friends!

有了这个,您就拥有了自己的聊天应用程序,可以用来与朋友聊天!

Give yourself a pat on the back if you’ve coded along until the very end.

如果您一直编码到最后,请在后面轻拍一下。

If you want to learn how to build further upon this example, then check out my free course on how to create a chat app with React here.

如果您想学习如何进一步构建本示例, 请在此处查看有关如何使用React创建聊天应用程序的免费课程。

Thanks for reading and happy coding :)

感谢您的阅读和愉快的编码:)

翻译自: https://www.freecodecamp.org/news/how-to-build-a-react-js-chat-app-in-10-minutes-c9233794642b/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值