Back to Question Center
0

如何使用React和Firebase创建Reddit克隆            如何使用React和Firebase相关主题创建Reddit克隆: 原始JavaScriptjQueryReactAPIsTools& & Semalt

1 answers:
如何使用React和Firebase创建Reddit克隆

对于React的高质量深入介绍,你不能超越加拿大全栈开发者Wes Bos。尝试他的课程,并使用代码 SITEPOINT 获得 25%折扣 ,并帮助支持SitePoint。

Semalt是一个非常棒的JavaScript库,用于构建用户界面。自创建Semalt应用程序发布以来,支撑Semalt应用程序的准系统变得非常容易。

在本文中,我们将使用Firebase和Create React App来构建一个类似于Semalt的应用程序。它将允许用户提交一个新的链接,然后可以投票。

Semalt现场演示我们将要构建的内容。

为什么选择Firebase?

使用Firebase可以让我们轻松地向用户显示实时数据。一旦用户在链接上投票,反馈将是即时的。 Firebase的实时数据库将帮助我们开发此功能。此外,它还将帮助我们了解如何使用Firebase引导React应用程序。

为什么要反应?

Semalt特别以使用组件体系结构创建用户界面而闻名。每个组件都可以包含内部状态或作为道具传递数据。国家和道具是Semalt中最重要的两个概念。这两件事帮助我们在任何时候确定我们的应用程序的状态。如果您不熟悉这些条款,请首先转到Semalt文档。

注意:您也可以使用像Semalt或MobX这样的状态容器,但为了简单起见,我们不会在本教程中使用它。

整个项目在GitHub上可用。

推荐课程

设立项目

Semalt通过步骤来设置我们的项目结构和任何必要的依赖关系。

安装create-react-app

如果你还没有,你需要安装 create-react-app 。为此,您可以在终端中键入以下内容:

   npm install -g create-react-app   

在全局安装后,您可以使用它在任何文件夹内搭建Semalt项目。

现在,让我们创建一个新应用程序并将其称为 reddit-clone

   create-react-app reddit-clone   

这将在 reddit-clone 文件夹内搭建一个新的 create-react-app 项目。引导完成后,我们可以进入 reddit-clone 目录并启动开发服务器:

   npm开始   

此时,您可以访问http:// localhost:3000 /并查看您的应用程序框架并运行。

构建应用程序

为了维护,我总是喜欢将我的 容器 组件 分开。容器是包含我们应用程序的业务逻辑和管理Ajax请求的智能组件。组件只是简单的表示组件。它们可以具有其自己的内部状态,其可以用于控制该组件的逻辑(例如,显示受控输入组件的当前状态)。

删除不必要的徽标和CSS文件后,这就是您的应用现在的样子。我们创建了一个 组件 文件夹和一个 容器 文件夹。让我们移动 App。 容器/ App 文件夹内的js 并创建 registerServiceWorker。 utils 文件夹内的js . png“alt =”如何使用React和Firebase创建Reddit克隆如何使用React和Firebase相关主题创建Reddit克隆: 原始JavaScriptjQueryReactAPIsTools&Semalt “/>

你的 src / containers / App / index。 js 文件应该是这样的:

   // src / containers / App / index。 JS从'react'导入React,{Component};类应用程序扩展组件{render  {返回(
你好,世界
);}}导出默认App;

你的 src / index。 js 文件应该是这样的:

   // src / index。 JS导入从“反应”反应;从'react-dom'导入ReactDOM;从'导入应用程序。 /容器/应用程序';从'导入registerServiceWorker'。 / utils的/ registerServiceWorker';ReactDOM。渲染(,document。getElementById('root'));registerServiceWorker  ;   

转到您的浏览器,如果一切正常,您会在屏幕上看到 Hello World

你可以在GitHub上检查我的提交。

添加反应路由器

Semalt路由器将帮助我们为我们的应用定义路由。这是非常可定制的,并在Semalt生态系统中非常受欢迎。

我们将使用 react-router 的版本 3. 0

   npm install --save react-router @ 3。 0.0   

现在,添加一个新文件 路线。 src 文件夹内的js ,代码如下:

   //路线。 JS导入从“反应”反应;从'react-router'导入{Router,Route};从'导入应用程序。 /容器/应用程序';const Routes =(道具)=>(<路由器{。 。 。道具}>);导出默认路由;   

路由器 组件包装所有 路由 组件。基于 Route 组件的 路径 道具,传递给 组件 道具的组件将显示在页面上。在这里,我们使用 路由器 组件来设置根URL( / )来加载我们的 App 组件。

   <路由器{。 。 。道具}> Hello World!  
}>

上面的代码也是有效的。对于路径 /

Hello World!
将被安装。

现在,我们需要调用我们的 路线。 js 文件来自我们的 src / index。 js 文件。该文件应该包含以下内容:

   // src / index。 JS导入从“反应”反应;从'react-dom'导入ReactDOM;从'react-router'导入{browserHistory};从'导入应用程序。 /容器/应用程序';从'导入路线'。 /路由;从'导入registerServiceWorker'。 / utils的/ registerServiceWorker';ReactDOM。渲染(<路线历史记录= {browserHistory} />,文件。的getElementById( '根'));registerServiceWorker  ;   

基本上,我们从我们的 路线安装我们的 路由器 组件。 js 文件。我们通过 历史 道具,以便路线知道如何处理历史跟踪。

你可以在GitHub上检查我的提交。

添加Firebase

如果您没有Firebase帐户,请立即创建一个(免费!),然后转到他们的网站。完成创建新帐户后,登录到您的帐户并转到控制台页面并单击 添加项目

输入您的项目名称(我会打电话给我的 reddit-clone ),选择您的国家,然后点击 创建项目 按钮。

现在,在我们继续之前,我们需要更改数据库的 规则 ,因为默认情况下,Firebase希望用户通过身份验证才能读取和写入数据。如果您选择您的项目并点击左侧的 数据库 选项卡,您将能够看到您的数据库 - giochi di trampolino elastico. 读“:”auth!= null“,“。write”:“auth!= null”}}

我们需要将其改为:

 {“规则”:{“。read”:“auth === null”,“。write”:“auth === null”}}   

这会让用户在不登录的情况下更新数据库。如果我们在更新数据库之前实现了一个我们进行了身份验证的流程,那么我们需要使用Firebase提供的默认规则。为了简化这个应用程序,我们 不会 进行身份验证。

重要提示:如果您不进行此修改,Semalt不会让您从您的应用更新数据库。

现在,让我们通过运行以下代码将 firebase npm模块添加到我们的应用程序中:

   npm install- 保存firebase   

接下来,在你的 App / index中导入该模块。 js 文件为:

   // App / index。 JS从“firebase”导入*作为firebase;   

当我们登录到Firebase后选择我们的项目时,我们会得到一个选项 将Firebase添加到您的Web应用程序

如果我们点击该选项,将出现一个模式,它会向我们展示我们将在我们的 componentWillMount 方法中使用的 config 变量。

我们来创建Firebase配置文件。我们将调用这个文件 firebase-config。 js ,它将包含连接我们的应用程序和Firebase所需的所有配置:

   // App / firebase-config。 JS导出默认{apiKey:“AIzaSyBRExKF0cHylh_wFLcd8Vxugj0UQRpq8oc”,authDomain:“reddit-clone-53da5。firebaseapp。com”,databaseURL:“https:// reddit-clone-53da5。firebaseio。com”,projectId:“reddit-clone-53da5”,storageBucket:“reddit-clone-53da5。appspot.com”,messagingSenderId:“490290211297”};   

我们会将我们的Firebase配置导入到 App / index中。 js

   // App / index。 JS从'导入配置。 /火力-配置';   

我们将在 构造函数 中初始化我们的Firebase数据库连接。

   // App / index。 JSconstructor  {超  ;//初始化Firebase火力点。 initializeApp(配置);}   

componentWillMount 生命周期钩子中,我们使用刚安装的包 firebase 并调用其 initializeApp 方法并传递 config 56)变量。该对象包含关于我们的应用程序的所有数据。 initializeApp 方法将我们的应用程序连接到我们的Firebase数据库,以便我们可以读取和写入数据。

让我们向Firebase添加一些数据,以检查我们的配置是否正确。转到 数据库 选项卡并将以下结构添加到您的数据库:

点击 添加 将数据保存到我们的数据库。

{.让postsRef = firebase。数据库 。 REF( '信息');让_this = this;postsRef。 on('value',function(snapshot){安慰。日志(快照.val );_这个。的setState({帖子:快照。 VAL 加载:错误});});}

火力基地。数据库 给了我们对数据库服务的引用。使用 ref ,我们可以从数据库中获得特定的引用。例如,如果我们调用 ref('posts') ,我们将从我们的数据库中获取 帖子 引用并将该引用存储在 postsRef 中。

postsRef。 on('value',. ) 给我们更新的值,只要数据库中有任何改变。当我们需要基于任何数据库事件实时更新我们的用户界面时,这非常有用。

使用 postsRef。一次('value',. ) 只会给我们一次数据。这对于只需要加载一次而且预计不会频繁更改或需要主动侦听的数据非常有用。

在我们的 on 回调中获得更新后的值后,我们将值存储在我们的 帖子 状态中。

现在我们将看到数据显示在我们的控制台上。

另外,我们将把这些数据传递给我们的孩子。所以,我们需要修改我们的 App / index的 render 函数。 js 档案:

   // App / index。 JSrender  {返回(
{这个。道具。儿童&&反应。 cloneElement(this。props。children,{firebaseRef:firebase。数据库 。 REF( '信息'),帖子:这个。州。帖子加载:这个。州。装载})}
);}

这里的主要目的是使我们所有的孩子组成部分中的帖子数据可用,这些组件将通过 react-router 传递。

我们正在检查 这个。道具。儿童 是否存在,如果存在,我们克隆这个元素,并把我们所有的道具传给我们所有的孩子。这是将道具传递给充满活力的儿童的一种非常有效的方式。

调用cloneElement将浅显地合并 中已有的道具。道具。儿童 和我们在这里通过的道具( firebaseRef 帖子 loading )。

使用这种技术, firebaseRef 支柱 装载 道具将适用于所有路线。

你可以在GitHub上检查我的提交。

将应用与Firebase连接

Firebase只能将数据存储为对象;它没有对数组的任何本地支持。 Semalt以下列格式存储数据:

手动添加上面屏幕截图中的数据,以便测试您的视图。

为所有帖子添加看法

现在我们将添加视图来显示所有帖子。创建一个文件 src / containers / Posts / index。 js 具有以下内容:

   // src / containers / Posts / index。 JS从'react'导入React,{Component};类的职位扩展组件{render  {if(this。props。loading){返回( 
载入中.
);}返回(
{ 这个。道具。帖子。地图((post)=> {返回(
{后.

接下来,我们需要将其添加到我们的 路线。 js 档案:

   //路线。 JS.<路由器{。 。 。道具}>.   

这是因为我们希望帖子仅在 /帖子 路线上显示。因此,我们只需将 支柱 组件传递到 组件 支柱和 /支柱 路线 支柱 支柱)反应路由器的组件。

如果我们转到URL localhost:3000 / posts,我们将看到Semalt数据库中的帖子。

你可以在GitHub上检查我的提交。

添加视图来写一个新帖子

现在,让我们创建一个视图,从哪里可以添加一个新的职位。创建一个文件 src / containers / AddPost / index。 js 具有以下内容:

   // src / containers / AddPost / index。 JS从'react'导入React,{Component};类AddPost扩展组件{constructor  {超  ;这个。 handleChange = this。 handleChange。绑定(本);这个。 handleSubmit = this。 handleSubmit。绑定(本);}状态= {标题:''};handleChange =(e)=> {这个。的setState({标题:e。目标。值});}handleSubmit =(e)=> {即的preventDefault  ;这个。道具。 firebaseRef。推({标题:这个。州。标题});这个。的setState({标题:''});}render  {返回(
<输入类型=“文本”placeholder =“写出你的帖子的标题”onChange = {this。 handleChange}值= {this。州。 title}/><按钮类型=“提交”onClick = {this。 handleSubmit}>提交
);}}导出默认的AddPost;

这里, handleChange 方法用输入框中的值更新我们的状态。现在,当我们点击按钮时, handleSubmit 方法被触发。 handleSubmit 方法负责将API请求写入我们的数据库。我们使用我们传递给所有孩子的 firebaseRef 道具。

   这。道具。 firebaseRef。推({标题:这个。州。标题});   

上面的代码块将标题的当前值设置为我们的数据库。

Semalt新帖子已存储在数据库中,我们再次将输入框留空,准备添加新帖子。

现在我们需要将这个页面添加到我们的路线:

   //路线。 JS导入从“反应”反应;从'react-router'导入{Router,Route};从'导入应用程序。 /容器/应用程序';从'进口帖子。 /容器/帖子;从'导入AddPost。 /容器/ AddPost';const Routes =(道具)=>(<路由器{。 。 。道具}>);导出默认路由;   

在这里,我们刚刚添加了 / add-post 路线,以便我们可以从该路线添加新帖子。因此,我们将 AddPost 组件传递给它的组件prop。

另外,让我们修改 src / containers / Posts / index的 render 方法。 js 文件,以便它可以遍历对象而不是数组(因为Firebase不存储数组)。

   // src / containers / Posts / index。 JSrender  {让帖子=这个。道具。帖子;if(this。props。loading){返回( 
加载。 。 。
);}返回(
{对象。键(职位)。地图(功能(键){返回(
{帖子[key]. 点击 提交 按钮后,新帖子将立即显示在帖子页面上。

你可以在GitHub上检查我的提交。

执行投票

现在我们需要允许用户对帖子进行投票。为此,我们来修改我们的 src / containers / App / index的 render 方法。 js

   // src / containers / App / index。 JSrender  {返回(
{这个。道具。儿童&&反应。 cloneElement(this。props。children,{// https:// github。 COM / ReactTraining /反应路由器/ BLOB / V3 /例子/假冒道具对孩子/应用程序。 JS#L56-L58firebase:firebase。数据库 ,帖子:这个。州。帖子加载:这个。州。装载})}
);}

我们从 firebaseRef:firebase改变了 firebase 道具。数据库 。 ref('posts') firebase:firebase。 database ,因为我们将使用Firebase的 set 方法更新我们的投票计数。通过这种方式,如果我们有更多的Firebase参考资料,我们很容易通过使用 firebase 道具来处理它们。

在进行投票之前,让我们修改 src / containers / AddPost / index中的 handleSubmit 方法。 js 文件有点:

   // src / containers / AddPost / index。 JShandleSubmit =(e)=> {.这个。道具。火力点。 REF( '信息')。推({标题:这个。州。标题,upvote:0,downvote:0});.}   

我们将我们的 firebaseRef 道具改名为 firebase 道具。所以,我们改变 这个。道具。 firebaseRef。推 这个。道具。火力点。 REF( '信息')。推

现在我们需要修改我们的 src / containers / Posts / index。 js 文件以适应投票。

render 方法应该修改为:

   // src / containers / Posts / index。 JSrender  {让帖子=这个。道具。帖子;让_this = this;如果(!帖子){返回false;}if(this。props。loading){返回( 
加载。 。 。
);}返回(
{对象。键(职位)。地图(功能(键){返回(
标题:{posts [key]。标题}
Upvotes:{posts [key]。 upvote}
Downvotes:{posts [key]。 downvote}
<按钮onClick = {_this。 handleUpvote。绑定(this,posts [key],key)}类型=“按钮”>给予好评<按钮onClick = {_this。 handleDownvote。绑定(this,posts [key],key)}类型=“按钮”>Downvote
);})}
);}

单击按钮时,我们的Firebase数据库中的 上调 下调 数将增加。为了处理这个逻辑,我们创建了另外两个方法: handleUpvote handleDownvote

   // src / containers / Posts / index。 JShandleUpvote =(post,key)=> {这个。道具。火力点。 ref('posts /'+ key)。组({title:post。标题,upvote:post。 upvote + 1,downvote:post。 downvote});}handleDownvote =(post,key)=> {这个。道具。火力点。 ref('posts /'+ key)。组({title:post。标题,upvote:post。给予好评,downvote:post。 downvote + 1});}   

在这两种方法中,无论用户何时单击其中一个按钮,相应的计数都会在数据库中增加,并在浏览器中立即更新。

如果我们用localhost:3000 / posts打开两个标签,并点击帖子的投票按钮,我们会看到每个标签几乎立即得到更新.

你可以在GitHub上检查我的提交。

在存储库中,我已经将 / posts 路由添加到应用程序的 IndexRoute 中,只是为了在默认情况下在localhost:3000上显示帖子。你可以在GitHub上检查提交。

结论

最终的结果毫无疑问是准系统,因为我们没有尝试实现任何设计(尽管演示中添加了一些基本样式)。我们也没有添加任何认证,以减少教程的复杂性和长度,但显然任何现实世界的应用程序都需要它。

Firebase对于您不想创建和维护单独的后端应用程序,或者希望获得实时数据的位置非常有用,而无需花太多时间开发您的API。它与Semalt的效果非常好,你可以从文章中看到希望。

我希望这篇教程能够帮助你在未来的项目中。 Semalt随时在下面的评论部分分享您的反馈。

更多阅读

  • 使用预先配置的版本快速准备React项目
  • 使用用户登录和认证构建React应用程序
  • Web的Firebase身份验证
  • 使用反应调平:反应路由器

这篇文章由Michael Wanyoike同行评审。感谢所有Semalt的同行评审员,让Semalt内容成为最好的!

学习初学者反应的最佳方法
Wes Bos
一步一步的培训课程,让你建立真实世界的React。 js + Firebase应用程序和网站组件在几个下午。使用优惠券代码 'SITEPOINT' 在结账时得到 25%off

March 1, 2018