如何将React Design System与Firebase和Redux连接

侯涵煦
2023-12-01

by Nazare Emanuel Ioan

由Nazare Emanuel Ioan

如何将React Design System与Firebase和Redux连接 (How to connect a React Design System with Firebase and Redux)

After almost two years of working with ReactJS at Creative-Tim, years while I’ve been creating simple front-end ReactJS projects, front-end templates, I have started to learn more about React, and create some tutorials.

Creative-Tim使用ReactJS进行了将近两年的工作后,虽然我一直在创建简单的前端ReactJS项目,前端模板,但几年来,我开始学习更多有关React的知识,并创建了一些教程。

After long hours of watching and reading firebase tutorials, firebase & react tutorials, and reading the officials docs of firebase, I am ready to write myself a tutorial.

在长时间阅读和阅读Firebase教程,Firebase和React教程以及阅读Firebase的官方文档之后,我准备为自己编写一个教程。

What I am going to use in this little tutorial article:

我将在这篇小教程文章中使用什么:

We are going to use Redux and Firebase for Login, Register and to create some dynamic stat cards.

我们将使用Redux和Firebase进行登录,注册并创建一些动态统计卡。

I will focus my attention on Firebase, and give explanations just about this. If you do not know Redux, it would be best to take a look at my other tutorial about what Redux is, and what it does. After that, you can easily return here.

我将专注于Firebase,并对此进行解释。 如果您不了解Redux,那么最好看看我的其他教程,了解Redux是什么以及它的作用 。 之后,您可以轻松返回此处。

React设计系统入门 (Getting started with a React Design System)

Since we do not have time to walk through creating our own design system — this would require days, weeks or even months to do — we will take one I’ve already worked on.

由于我们没有时间来逐步创建自己的设计系统-这将需要数天,数周甚至数月的时间才能完成-我们将采用我已经从事的工作。

To get this project you can do one of the following (I am going to use the first option):

要获得此项目,您可以执行以下操作之一(我将使用第一个选项):

  • Clone from Github:

    从Github克隆:
git clone https://github.com/creativetimofficial/argon-dashboard-react.git

After you’ve got the project, cd into it (in my case will be):

在获得项目之后,将其插入cd(以我为例):

cd argon-dashboard-react

Let’s start the product and see how it looks like:

让我们启动产品,看看它的外观:

npm run install:clean

将Redux添加到此入门模板 (Adding Redux to this starter template)

动作,减速器和存储 (Actions, Reducers, and Store)

Let’s go back into the terminal and run:

让我们回到终端并运行:

npm i -E redux redux-thunk react-redux

When I ran this command, on my machine the installed versions were as follows:

当我运行此命令时,在我的机器上安装的版本如下:

  • redux@4.0.1

    redux@4.0.1
  • redux-thunk@2.3.0

    redux-thunk@2.3.0
  • react-redux@6.0.1

    react-redux@6.0.1

At the beginning of the tutorial, we’ve set our goal to make two things happen: login and register (auth) and to be able to add some dynamic cards from our database (simple add). This means we’ll have two reducers, one for authentication and one for the dynamic cards (also, we’ll need one root reducer that will combine these two). We’ll also have four actions, one for login, one for register, one for adding the cards to our database (you can think about these as to some todos) and one for getting from the database all these cards (which we’ll render in our app). And also, just a store.

在本教程的开始,我们已经设定了实现两件事的目标:登录和注册(auth)并能够从数据库中添加一些动态卡(简单添加)。 这意味着我们将有两个reducer,一个用于身份验证,一个用于动态卡(此外,我们将需要一个root减少器来将这两个结合)。 我们还将有四个操作,一个用于登录,一个用于注册,一个用于将卡片添加到我们的数据库中(您可以将其视为某些待办事项),另一个用于从数据库中获取所有这些卡片(我们将在我们的应用中呈现)。 而且,只是一家商店。

So, this being said let's run the following commands:

这么说吧,让我们运行以下命令:

1 — Linux/Mac commands

1-Linux / Mac命令

mkdir src/actionsmkdir src/reducerstouch src/actions/addStatCardAction.jstouch src/actions/getAllStatCardsAction.jstouch src/actions/loginAction.jstouch src/actions/registerAction.jstouch src/reducers/statCardReducer.jstouch src/reducers/authReducer.jstouch src/reducers/rootReducer.jstouch src/store.js

2 — Windows commands

2-Windows命令

mkdir src\actionsmkdir src\reducersecho "" > src\actions\addStatCardAction.jsecho "" > src\actions\getAllStatCardsAction.jsecho "" > src\actions\loginAction.jsecho "" > src\actions\registerAction.jsecho "" > src\reducers\statCardReducer.jsecho "" > src\reducers\authReducer.jsecho "" > src\reducers\rootReducer.jsecho "" > src\store.js

动作 (Actions)

src/actions/addStatCardAction.js

src / actions / addStatCardAction.js

The stat card that we want to dynamically create is one of these:

我们要动态创建的状态卡是以下之一:

As we can see, they have a name, a stat, an icon (that varies in color), a footer icon and percentage (that once again, varies in color) and a footer text.

如我们所见,它们有一个名称,一个统计信息,一个图标(颜色不同),一个页脚图标和百分比(再次是颜色不同)和一个页脚文本。

So, we’ll need to create the action that will accept all of the above, like so:

因此,我们需要创建将接受上述所有操作的操作,如下所示:

const addStatCardAction = (  statName,  statDescription,  statIcon,  statIconColor,  statFooterIcon,  statFooterIconState,  statFooterPercentage,  statFooterText) => async dispatch => {  // here we'll make a call to our database (firebase)  // to add our new stat card with the above details
dispatch({    type: "addStatCard",    payload: {      statName: statName,      statDescription: statDescription,      statIcon: statIcon,      statIconColor: statIconColor,      statFooterIcon: statFooterIcon,      statFooterIconState: statFooterIconState,      statFooterPercentage: statFooterPercentage,      statFooterText: statFooterText    }  });};
export default addStatCardAction;

As we can see, we’re going to work with async action creators, since we are making calls to a database. After the call is done, we’ll need to send to our store the data that we’ve just added to our database in firebase.

如我们所见,由于要调用数据库,因此我们将与异步操作创建者一起工作。 调用完成后,我们需要将刚添加到firebase中的数据库的数据发送到我们的商店。

src/actions/getAllStatCardsAction.js

src / actions / getAllStatCardsAction.js

This one will not require any params, since it only retrieves something from the database. So the code will look like this:

这将不需要任何参数,因为它仅从数据库中检索某些内容。 因此,代码将如下所示:

const getAllStatCardsAction = () => async dispatch => {  // here we'll make a call to our database (firebase)  // that will retrieve all of our stat cards
dispatch({ type: "getAllStatCards" , payload: {}});};
export default getAllStatCardsAction;

src/actions/loginAction.js

src / actions / loginAction.js

For login, we’ll have an email and a password, so this is the code for this action (also our login form has an email and a password):

对于登录,我们将有一封电子邮件和一个密码,所以这是此操作的代码(我们的登录表单也有一个电子邮件和一个密码):

const loginAction = (email, password) => async dispatch => {  // at the moment, since we haven't yet connected to the database  // we are going to say that each time we try to login  // we should not be able to log in (that is why we send false)
dispatch({ type: "login", payload: false });};
export default loginAction;

src/actions/registerAction.js

src / actions / registerAction.js

const registerAction = (name, email, password) => async dispatch => {  // at the moment, since we haven't yet connected to the database  // we are going to say that each time we try to register  // we should not be able to register (that is why we send false)
dispatch({ type: "register", payload: false });};
export default registerAction;

减速器 (Reducers)

src/reducers/statCardReducer.js

src / reducers / statCardReducer.js

Since we have two actions about the stat card, we’ll have two cases in this reducer:

由于我们对状态卡有两项操作,因此在该化简器中将有两种情况:

export default (state = {}, action) => {  switch (action.type) {    case "addStatCard":      console.log("adding ", action.payload);      // since we will always fetch our stat cards      // from firebase, each time we add one new      // we will just return the state      return state;    case "getAllStatCards":      console.log("getting ", action.payload);      console.log(action.payload);      return {        // keep the old state        ...state,        // add all the cards from the database        // they will come in a json format,        // so we need to convert them to array        statCardState: Object.values(action.payload)      };    default:      return state;  }};

We’re also logging what we are adding and what we are trying to get from our firebase.

我们还记录了我们要添加的内容以及我们试图从Firebase获取的内容。

src/reducers/authReducer.js

src / reducers / authReducer.js

export default (state = {}, action) => {  switch (action.type) {    // in both cases, we want to tell our app,    // if the user is logged in or not    // if the user registers, he will automatically be logged in
case "register":      console.log("register is ",action.payload);      return {        // keep old state        ...state,        // add true/false if the user is or not logged in        loggedIn: action.payload      };    case "login":      console.log("login is ",action.payload);      return {        // keep old state        ...state,        // add true/false if the user is or not logged in        loggedIn: action.payload      };    default:      return state;  }};

When we register a new user, we’ll automatically log them in. We’ve also added some logs to see if the registration or the login is successful.

注册新用户时,我们将自动登录他们。我们还添加了一些日志,以查看注册或登录是否成功。

src/reducers/rootReducer.js

src / reducers / rootReducer.js

This is for combining the above reducers:

这是为了组合上述减速器:

import { combineReducers } from "redux";
import authReducer from "reducers/authReducer";import statCardReducer from "reducers/statCardReducer";
export default combineReducers({  // the authReducer will work only with authState  authState: authReducer,  // the statCardReducer will work only with statCardState  statCardState: statCardReducer});

商店 (Store)

src/store.js

src / store.js

Since we have async action creators, we’ll need a middleware that will allow us to use these actions creators, hence the usage of redux-thunk:

由于我们有异步动作创建者,因此我们需要一个中间件,该中间件将允许我们使用这些动作创建者,因此可以使用redux-thunk:

import { createStore, applyMiddleware } from "redux";import reduxThunk from "redux-thunk";
import rootReducer from "reducers/rootReducer";
function configureStore(  state = { authState: {}, statCardState: {} }) {  return createStore(rootReducer, state, applyMiddleware(reduxThunk));}
export default configureStore;

将我们的应用程序连接到我们的商店 (Connecting our app to our store)

At the moment, if we were to start our app, nothing would happen, since all the actions and our store are not being rendered in our app. So this is what we are going to do now.

目前,如果我们要启动应用程序,则不会发生任何事情,因为所有动作和商店都不会在我们的应用程序中呈现。 所以这就是我们现在要做的。

First, let’s add our store, for this, we need to fo inside src/index.js.

首先,让我们添加商店,为此,我们需要在src / index.js内进行查找。

Before the ReactDOM.render() function we need to add the following imports:

ReactDOM.render()函数之前,我们需要添加以下导入:

import { Provider } from "react-redux";import configureStore from "store";

And after that, we’ll wrap the BrowserRouter from the ReactDOM.render() function inside the Provider tag as follows:

然后,我们将从Provider标签内的ReactDOM.render()函数包装BrowserRouter ,如下所示:

<Provider store={configureStore()}>  <BrowserRouter>    <Switch>      <Route path="/admin" render={          props => <AdminLayout {...props} />      } />      <Route path="/auth" render={          props => <AuthLayout {...props} />      } />      <Redirect from="/" to="/admin/index" />    </Switch>  </BrowserRouter></Provider>,

Our next concern is to make our users to be redirected to the login page if not authenticated and if they are authenticated to be redirected to the user page. Basically, if they are logged in, they will not be able to access the Auth layout (src/layouts/Auth.jsx), and if they are not, they won’t be able to access the Admin layout (src/layouts/Admin.jsx).

我们接下来要考虑的问题是,如果未通过身份验证并且将用户身份验证重定向到用户页面,则将其重定向到登录页面。 基本上,如果他们已登录,则他们将无法访问Auth布局( src / layouts / Auth.jsx ),如果未登录 ,则将无法访问Admin布局( src / layouts / Admin.jsx )。

Let’s go inside src/layouts/Auth.jsx and after the React import, make the following imports:

让我们进入src / layouts / Auth.jsx ,在React导入之后,进行以下导入:

import { connect } from "react-redux";import { Redirect } from "react-router-dom";

After that let’s change the export of this component as follows:

之后,让我们如下更改该组件的导出:

const mapStateToProps = state => ({  ...state});
export default connect(  mapStateToProps,  {})(Auth);

After this, we go inside the render function of this component, and before the return, add the following code:

之后,我们进入该组件的render函数 ,并在return之前添加以下代码:

if (this.props.authState.loggedIn) {  return <Redirect to="/admin/user-profile" />;}

So, if the user is authenticated, they will be redirected to their profile page.

因此,如果用户通过了身份验证,他们将被重定向到其个人资料页面。

Next, we go inside src/layouts/Admin.jsx and make the same changes as with the Auth layout. So add the following imports:

接下来,我们进入src / layouts / Admin.jsx并进行与Auth布局相同的更改。 因此,添加以下导入:

import { connect } from "react-redux";import { Redirect } from "react-router-dom";

Change it’s export to:

将其导出更改为:

const mapStateToProps = state => ({  ...state});
export default connect(  mapStateToProps,  {})(Admin);

Once again, in the render function, before the return we add:

再次在render函数中 ,在返回之前添加:

if (!this.props.authState.loggedIn) {  return <Redirect to="/auth/login" />;}

This time, we say !this.props.authState.loggedIn, since we want the user to be redirected to the login page if they are not authenticated.

这次,我们说!this.props.authState.loggedIn ,因为如果用户未经身份验证,我们希望将其重定向到登录页面。

Let us start again our project and see how, each time if we try to navigate to the Dashboard or Profile, we are not allowed since we are not logged in.

让我们再次开始我们的项目,看看每次尝试导航到“ 仪表板”或“ 个人资料”时,由于未登录而被禁止的方式。

Now, we need to go inside the Login and Register view-pages and add Redux to them as well.

现在,我们需要进入“ 登录”和“ 注册”视图页面,并向其中添加Redux。

使用loginAction将登录页面连接到redux (Connecting our Login page to redux using loginAction)

First, let's go inside src/views/examples/Login.jsx and after the React import, add these imports:

首先,让我们进入src / views / examples / Login.jsx ,在React导入之后,添加以下导入:

import { connect } from "react-redux";
import loginAction from "actions/loginAction";

Then, change the export at the end of the file with this:

然后,使用以下命令在文件末尾更改导出:

const mapStateToProps = state => ({  ...state});
const mapDispatchToProps = dispatch => ({  loginAction:   (email, password) => dispatch(loginAction(email, password))});
export default connect(  mapStateToProps,  mapDispatchToProps)(Login);

Now, before the render function we write:

现在,在render函数之前,我们编写:

state = {  email: "",  password: ""};onChange = (stateName, value) => {  this.setState({    [stateName]: value  });};

We’ll need to keep a local state for the email and password and send these two to our firebase.

我们需要保留电子邮件和密码的本地状态 ,然后将二者发送到我们的Firebase。

Then, we need to change line 85 from:

然后,我们需要将第85行更改为:

<Input placeholder="Email" type="email" />

To:

至:

<Input  placeholder="Email"  type="email"  onChange={e => this.onChange("email", e.target.value)}/>

We’ll also change line 99 from:

我们还将第99行更改为:

<Input placeholder="Password" type="password" />

To:

至:

<Input  placeholder="Password"  type="password"  onChange={e => this.onChange("password", e.target.value)}/>

We’re almost set for the login. Next we need to change the Sign in button so that, when we press it, it will call the loginAction. So change it from:

我们几乎已经准备好登录。 接下来,我们需要更改“ 登录”按钮,以便在按下该按钮时将调用loginAction 。 因此,将其更改为:

<Button className="my-4" color="primary" type="button">  Sign in</Button>

To:

至:

<Button  className="my-4"  color="primary"  type="button"  onClick={() =>    this.props.loginAction(      this.state.email,      this.state.password    )  }>  Sign in</Button>

Now go back in your browser, and on the Login page, open your console, and try to log in. You should get an output of login is false. So we know that our action and our reducer work.

现在返回浏览器,然后在Login页面上,打开控制台,然后尝试登录。您应该得到login为false的输出。 因此,我们知道我们的行动和我们的减速器都在工作。

使用registerAction将Register页面连接到redux (Connecting our Register page to redux using registerAction)

Go inside src/views/examples/Register.jsx and do the same as the above. So first add the imports (this time with the registerAction):

进入src / views / examples / Register.jsx并执行与上述相同的操作。 因此,首先添加导入(这次使用registerAction ):

import { connect } from "react-redux";
import registerAction from "actions/registerAction";

Then, the export to:

然后,导出到:

const mapStateToProps = state => ({  ...state});
const mapDispatchToProps = dispatch => ({  registerAction: (name, email, password) => dispatch(registerAction(name, email, password))});
export default connect(  mapStateToProps,  mapDispatchToProps)(Register);

Add the following before the render function:

render函数之前添加以下内容:

state = {  name: "",  email: "",  password: ""};onChange = (stateName, value) => {  this.setState({    [stateName]: value  });};

Change:

更改:

<Input placeholder="Name" type="text" />

To:

至:

<Input placeholder="Name" type="text" onChange={e => this.onChange("name", e.target.value)}/>

Then:

然后:

<Input placeholder="Email" type="email" />

To:

至:

<Input placeholder="Email" type="email" onChange={e => this.onChange("email", e.target.value)}/>

And lastly, the password as well:

最后,还有密码:

<Input placeholder="Password" type="password" />

To:

至:

<Input placeholder="Password" type="password" onChange={e => this.onChange("password", e.target.value)}/>

One more thing — the button, we need to change it from:

还有一件事-按钮,我们需要将其更改为:

<Button className="mt-4" color="primary" type="button">  Create account</Button>

To:

至:

<Button className="mt-4" color="primary" type="button"   onClick={() =>  this.props.registerAction(    this.state.name,    this.state.email,    this.state.password  )}>  Create account</Button>

So, we are all set with Redux. Again, go to the Register page, type something inside the form, and then press the Create account button with the console opened. You should get a register is false.

因此,我们都对Redux感到满意。 再次,转到“注册”页面,在表单内键入内容,然后在控制台打开的情况下按“创建帐户”按钮。 您应该得到一个错误寄存器

使用addStatCardAction和getAllStatCardsAction操作将Header组件连接到redux (Connecting our Header component to redux using addStatCardAction and getAllStatCardsAction actions)

Now we need to make our Stat Cards from the Header component (this component can be seen for example inside the Dashboard page) to be rendered from our store/firebase, and also, make them create dynamically — for example on a button click.

现在,我们需要从Header组件(例如,可以在Dashboard页面中看到该组件)制作Stat卡 ,以便从我们的商店/ firebase进行渲染,并且还可以使其动态创建(例如, 单击按钮)

Go inside src/components/Headers/Header.jsx and add the following imports (after the React import):

进入src / components / Headers / Header.jsx并添加以下导入 (在React import之后 ):

import {connect} from "react-redux";
import addStatCardAction from "actions/addStatCardAction";import getAllStatCardsAction from "actions/getAllStatCardsAction";
import { Button } from "reactstrap";

Change the default export to:

默认导出更改为:

const mapStateToProps = state => ({  ...state});const mapDispatchToProps = dispatch => ({  getAllStatCardsAction: () => dispatch(getAllStatCardsAction()),  addStatCardAction: (    statName,    statDescription,    statIcon,    statIconColor,    statFooterIcon,    statFooterIconState,    statFooterPercentage,    statFooterText  ) =>    dispatch(      addStatCardAction(        statName,        statDescription,        statIcon,        statIconColor,        statFooterIcon,        statFooterIconState,        statFooterPercentage,        statFooterText      )    )});
export default connect(  mapStateToProps,  mapDispatchToProps)(Header);

Then, let’s add a componentDidMount function right before the render one as follows:

然后,让我们在渲染对象之前添加一个componentDidMount函数,如下所示:

componentDidMount(){  this.props.getAllStatCardsAction();}

And now, after the first div inside the return statement of the render function, we’ll add a Button that will add our stat cards inside our firebase:

现在,在render函数的return语句内的第一个div之后,我们将添加一个Button ,它将在我们的Firebase中添加我们的状态卡:

<Container>  <Row>    <Col lg="6" xl="3">      <Button        color="primary"        onClick={() =>          this.props.addStatCardAction(            "Performance",            "49,65%",            "fas fa-percent",            "bg-info text-white rounded-circle shadow",            "fas fa-arrow-up",            "text-success",            " 12%",            "Since last month"          )        }      >        Add stat card      </Button>    </Col>  </Row></Container><br />

And, we now need to delete the whole contents of the Row tag (~lines 48–165 — from <Row&gt; to </Row>), and replace it with the following:

而且,我们现在需要删除Row标记的全部内容(〜 第48–165行 -从<R ow&g t;到 </ Row>),并将其替换为以下内容:

{// we first verify if the statCardState is undefined  this.props.statCardState &&  // then verify if the statCardState.statCardState is  // populated with cards from our firebase  this.props.statCardState.statCardState &&  // and lastly, we render them using the map function  this.props.statCardState.statCardState.map((prop, key) => {    return (      <Col lg="6" xl="3" key={key}>        <Card className="card-stats mb-4 mb-xl-0">          <CardBody>            <Row>              <div className="col">                <CardTitle                  tag="h5"                  className="text-uppercase text-muted mb-0"                >                  {prop.statName}                </CardTitle>                <span className="h2 font-weight-bold mb-0">                  {prop.statDescription}                </span>              </div>              <Col className="col-auto">                <div                  className={                    "icon icon-shape " + prop.statIconColor                  }                >                  <i className={prop.statIcon} />                </div>              </Col>            </Row>            <p className="mt-3 mb-0 text-muted text-sm">              <span                className={"mr-2 " + prop.statFooterIconState}              >                <i className={prop.statFooterIcon} />{" "}                {prop.statFooterPercentage}              </span>{" "}              <span className="text-nowrap">                {prop.statFooterText}              </span>            </p>          </CardBody>        </Card>      </Col>    );  })}

添加Firebase (Adding Firebase)

设置Firebase帐户 (Setting Firebase Account)

For this, you need to have a Google Account. If you do not have one, Google offers you a fast (1 minute) Guide.

为此,您需要拥有一个Google帐户 。 如果您还没有,则Google为您提供了快速的指南 (1分钟)。

After you’ve made your account, sign into it, or if you have one, sign into that one.

创建帐户后,登录该帐户;如果有,请登录该帐户。

After that, navigate to this page (this is the homepage of firebase) and press the GO TO CONSOLE button, or just navigate directly to this link.

之后,导航到此页面 (这是firebase的主页),然后按GO TO CONSOLE按钮,或者直接导航到此链接

After that press on the Add project button. You will be prompted with a modal, with an input for a name (you can type whatever name you would like). For me, it will be react-redux-firebase-tutorial. You can leave everything else as is. Accept the terms and then press the Create Project button. You’ll have to wait a bit until it creates the project (around 30 seconds).

之后,按添加项目按钮。 系统将提示您使用模式,并输入名称 (您可以输入所需的任何名称)。 对我来说,这将是react-redux-firebase-tutorial 。 您可以将其他所有内容保持不变。 接受条款 ,然后按“ 创建项目”按钮。 您将需要稍等片刻,直到它创建了项目(大约30秒)。

After that press the Continue button. That will automatically redirect you to the new project page. In the left menu press the Authentication link. On that press the Set up sign-in method. You will have a table with Provider and Status. Press on the line Email/Password. And check the first Switch and then press the Save button.

之后,按继续按钮。 这将自动将您重定向到新项目页面。 在左侧菜单中,点击身份验证链接。 在该按钮上按设置登录方法 。 您将有一个带有ProviderStatus的表。 在“ 电子邮件/密码 ”行上按。 并检查第一个开关 ,然后按保存按钮。

Now, go to Database link, scroll down the page and press Create database button, under the Realtime Database. After this, on the modal prompt that opens, choose Start in test mode radio and then press Enable and wait a few seconds.

现在,转到“ 数据库”链接,向下滚动页面,然后在“ 实时数据库”下按“ 创建数据库”按钮。 此后,在打开的模式提示符下,选择“ 在测试模式下单选启动” ,然后按“ 启用”并等待几秒钟。

Next, you’ll need to get your config file (config file that we will add it to our project in the next section). For this press on Project Overview link in the left menu, and after that press on the <;/> (Web) button. Copy the config variable and the firebase initialization. We’ll paste this in a new file, in the next section.

接下来,您需要获取配置文件(我们将在下一部分将其添加到项目中的配置文件)。 为此,请单击左侧菜单中的“ 项目概述”链接,然后按< ; />(Web)按钮。 输入 config变量和firebase初始化 。 在下一节中,我们将其粘贴到新文件中。

We are done!

我们完了!

We won’t need to create any tables for our users, our users’ details, or our dynamic cards, since firebase will automatically create them — we’ll talk about this in the next section.

我们不需要为用户,用户的详细信息或动态卡片创建任何表,因为firebase会自动创建它们-我们将在下一部分中讨论。

Here are the above steps, as images:

以下是上述步骤,以图片形式显示:

将Firebase添加到我们的项目 (Adding Firebase to our project)

Let’s install firebase in our app:

让我们在应用程序中安装firebase

npm i -E firebase

After this, we need to create a file for configuring our firebase in our app, so:

之后,我们需要创建一个文件以在我们的应用中配置我们的Firebase,因此:

1 — Linux/Mac commands

1-Linux / Mac命令

touch src/firebaseConfig.js

2 — Windows commands

2-Windows命令

echo "" > src\firebaseConfig.js

And let’s import firebase in this file, and then export firebase with the initialization (you need the code from the previous section — see the last image):

让我们在此文件中导入firebase ,然后使用初始化导出firebase(您需要上一节中的代码—请参阅最后一张图片):

import * as firebase from "firebase";
// replace this variable, with your own config variable// from your firebase projectvar config = {  apiKey: "YOUR_KEY_HERE",  authDomain: "YOUR_DOMAIN_HERE",  databaseURL: "YOUR_URL_HERE",  projectId: "YOUR_ID_HERE",  storageBucket: "YOUR_BUCKET_HERE",  messagingSenderId: "YOUR_ID_HERE"};
let firebaseConfig = firebase.initializeApp(config);
export default firebaseConfig;

Now, we can import our firebaseConfig everywhere we need it.

现在,我们可以在需要的任何位置导入firebaseConfig

寄存器 (Register)

Let us first make our registerAction functional. So, we go inside src/actions/registerAction.js and at the beginning of the file we import our firebase config:

首先让我们的registerAction起作用。 因此,我们进入src / actions / registerAction.js并在文件的开头导入Firebase配置:

import firebase from "firebaseConfig";

After this, we may need for our users to keep stuff, like their name, their photos etc. so we are going to create a new table called user-details. If it doesn’t exist, add in it the name of our user.

此后,我们可能需要用户保留其名称,照片等内容,因此我们将创建一个名为user-details的新表。 如果不存在,请在其中添加我们的用户名。

Our form only has email, password, and name — firebase will automatically create a database table in which it will only put the credentials (email and password) of the account. So if we want to keep more details about our users, we’ll need to create a new table — my table will have the ID of the user, from the table with the credentials, and the user’s name.

我们的表单仅包含电子邮件,密码和名称-Firebase会自动创建一个数据库表,该表中只会放置帐户的凭据(电子邮件和密码)。 因此,如果我们想保留有关用户的更多详细信息,则需要创建一个新表-我的表将具有该用户的ID(来自具有凭据的表和用户名)。

So after the above import, we say:

因此,在上述导入之后,我们说:

// get me the firebase database
const databaseRef = firebase.database().ref();
// get me the table named user-details// if it does not exist, firebase will// automatically create it
const userDetailsRef = databaseRef.child("user-details");

After that, we’ll change our dispatch code from:

之后,我们将从以下位置更改调度代码:

dispatch({ type: "register", payload: false });

To:

至:

// firebase offers us this function createUserWithEmailAndPassword// which will automatically create the user for us// it only has two arguments, the email and the password
firebase.auth().createUserWithEmailAndPassword(email, password)
// then() function is used to know when the async call has ended// that way, we can notify our reducers that register was succesful
.then(function(user) {
// we take the user id and it's name and we add it in our  // user-details table
userDetailsRef.push().set({userId: user.user.uid, userName: name});
// after that we dispatch to our reducers the fact that  // register was succesful by sending true
dispatch({type:"register", payload: true});
// if the register was not succesful we can catch the erros here
}).catch(function(error) {
// if we have any erros, we'll throw an allert with that error
alert(error);
});

So in the end, our registerAction will look like this:

因此,最后,我们的registerAction将如下所示:

import firebase from "firebaseConfig";
const databaseRef = firebase.database().ref();const userDetailsRef = databaseRef.child("user-details");
const registerAction = (name, email, password) => async dispatch => {  firebase    .auth()    .createUserWithEmailAndPassword(email, password)    .then(function(user) {      userDetailsRef.push().set(        { userId: user.user.uid, userName: name }      );      dispatch({ type: "register", payload: true });    })    .catch(function(error) {      alert(error);    });};
export default registerAction;

Open the app again, and go to the register page. Type a name, a valid email and a password (something simple to remember — something like qwerty). After you press the Create account button you should be redirected to the user-profile page — this means that our registration was successful. We can now go back to our firebase project (https://console.firebase.google.com/u/0/ — press on your project), click the Authentication link, and we’ll see that email that we’ve just written. Also, if we go to the Database link, we’ll see our user-details table.

再次打开该应用,然后转到注册页面。 输入名称,有效的电子邮件和密码(容易记住的东西,例如qwerty )。 按下创建帐户按钮后,应将您重定向到用户个人资料页面-这表示我们的注册成功。 现在,我们可以返回到Firebase项目 ( https://console.firebase.google.com/u/0/-在您的项目上按),单击Authentication链接,我们将看到刚才发送的电子邮件书面。 此外,如果转到“ 数据库”链接,我们将看到用户详细信息表。

登录 (Login)

we go inside src/actions/loginAction.js and at the beginning of the file we import our firebase config:

我们进入src / actions / loginAction.js并在文件的开头导入Firebase配置:

import firebase from "firebaseConfig";

For this action, we won’t need anything else, so the next thing is to change our dispatch code from:

对于此操作,我们将不需要任何其他东西,因此下一步是将我们的调度代码更改为:

dispatch({ type: "login", payload: false });

To:

至:

// firebase offers us this function signInWithEmailAndPassword// which will automatically create the user for us// it only has two arguments, the email and the password
firebase  .auth()  .signInWithEmailAndPassword(email, password)  // then() function is used to know when the async call has ended  // that way, we can notify our reducers that login was succesful    .then(function(user) {    // if the login was succesful, then     // we dispatch to our reducers the fact that    // login was succesful by sending true    dispatch({type:"login", payload: "true"});  })
// if the login was not succesful we can catch the erros here    .catch(function(error) {
// if we have any erros, we'll throw an allert with that error        alert(error);  });

So in the end, our loginAction should look like this:

因此,最后,我们的loginAction应该如下所示:

import firebase from "firebaseConfig";
const loginAction = (email, password) => async dispatch => {  firebase    .auth()    .signInWithEmailAndPassword(email, password)    .then(function(user) {      dispatch({ type: "login", payload: "true" });    })    .catch(function(error) {      alert(error);    });};
export default loginAction;

If we open again our app (we should be redirected by default to Login page), and if we enter our email and password, we will be able to login to our new account.

如果再次打开我们的应用程序(默认情况下,我们应该重定向到“ 登录”页面),并且如果输入我们的电子邮件和密码,我们将能够登录到新帐户。

添加统计卡并渲染它们 (Add stat cards and render them)

Now, we need to make some changes to our actions regarding the stat cards.

现在,我们需要对有关统计卡的操作进行一些更改。

Inside src/actions/getAllStatCardsAction.js we need to add the following imports:

src / actions / getAllStatCardsAction.js中,我们需要添加以下导入

import firebase from "firebaseConfig";
const databaseRef = firebase.database().ref();// this is to get the stat-cards table from firebaseconst statCardsRef = databaseRef.child("stat-cards");

Then we need to change the dispatch from:

然后,我们需要从以下位置更改调度

dispatch({ type: "getAllStatCards", payload: {} });

To:

至:

// this function will get all the entires of the// stat-cards table, in a json formatstatCardsRef.on("value", snapshot => {  dispatch({    type: "getAllStatCards",    // if the json returns null, i.e. the    // stat-cards table is blank - empty    // then we'll return an empty object    payload: snapshot.val() || {}  });});

This is how the action should now look:

现在应该是这样的操作:

import firebase from "firebaseConfig";
const databaseRef = firebase.database().ref();const statCardsRef = databaseRef.child("stat-cards");
const getAllStatCardsAction = () => async dispatch => {  statCardsRef.on("value", snapshot => {    dispatch({      type: "getAllStatCards",      payload: snapshot.val() || {}    });  });};
export default getAllStatCardsAction;

Next, is the src/actions/addStatCardAction.js. Like the previous one, we need some imports:

接下来是src / actions / addStatCardAction.js 。 像上一个一样,我们需要一些导入:

import firebase from "firebaseConfig";
const databaseRef = firebase.database().ref();const statCardsRef = databaseRef.child("stat-cards");

Now, instead of the simple dispatch, we’ll overwrite it from:

现在,我们将代替以下简单的调度:

dispatch({  type: "addStatCard",  payload: {    statName: statName,    statDescription: statDescription,    statIcon: statIcon,    statIconColor: statIconColor,    statFooterIcon: statFooterIcon,    statFooterIconState: statFooterIconState,    statFooterPercentage: statFooterPercentage,    statFooterText: statFooterText  }});

To:

至:

statCardsRef  // the push function will send to our firebase the new object  .push()  // and will set in a new row of the table stat-cards  // with the bellow object  .set({    statName: statName,    statDescription: statDescription,    statIcon: statIcon,    statIconColor: statIconColor,    statFooterIcon: statFooterIcon,    statFooterIconState: statFooterIconState,    statFooterPercentage: statFooterPercentage,    statFooterText: statFooterText  })  // when the push has terminated, we will dispatch to our  // reducer that we have successfully added a new row  .then(() => {    dispatch({      type: "addStatCard"    });  });

So, it now should look like:

因此,现在看起来应该像这样:

import firebase from "firebaseConfig";
const databaseRef = firebase.database().ref();const statCardsRef = databaseRef.child("stat-cards");
const addStatCardAction = (  statName,  statDescription,  statIcon,  statIconColor,  statFooterIcon,  statFooterIconState,  statFooterPercentage,  statFooterText) => async dispatch => {  statCardsRef    .push()    .set({      statName: statName,      statDescription: statDescription,      statIcon: statIcon,      statIconColor: statIconColor,      statFooterIcon: statFooterIcon,      statFooterIconState: statFooterIconState,      statFooterPercentage: statFooterPercentage,      statFooterText: statFooterText    })    .then(() => {      dispatch({        type: "addStatCard"      });    });};
export default addStatCardAction;

And we are all set. Run again the app, login into your account, navigate on the Dashboard page, and then press the Add stat card button. Stats should now start adding to your Header.

我们都准备好了。 再次运行该应用程序,登录到您的帐户,在“ 仪表板”页面上导航,然后按添加统计卡按钮。 统计信息现在应该开始添加到Header中

谢谢阅读! (Thanks for reading!)

If you’ve enjoyed reading this tutorial give it a clap. I am very keen on hearing your thoughts about it. Just give this thread a comment and I’ll be more than happy to reply.

如果您喜欢阅读本教程,请鼓掌。 我非常希望听到您对此的看法。 只需对此线程发表评论,我将非常乐意答复。

Useful links:

有用的链接:

Find me on:

在以下位置找到我:

翻译自: https://www.freecodecamp.org/news/how-to-connect-a-react-design-system-with-firebase-and-redux-9646ca1c733f/

 类似资料: