【翻译】React入门教程:概述和实例

本文译自Tinia Rascia的《React Tutorial: An Overview and Walkthrough》。文章标题本站翻译为《React入门教程:概述和实例》。该文是React官网推荐的入门教程之一,文章从传统的Javascript开始讲起,讲述了React的基本概念和相关术语,并学习了相关术语。文章比较适合具有一定的HTML、CSS、Javascript基础的读者。

文章为本站(txeet.com)翻译。转载并翻译本文的目的仅是为了学习。如果你想转载本文,请联系本站并注明来源。

Tinia Rascia的文章链接:https://www.taniarascia.com/getting-started-with-react/,建议有英文阅读能力的读者直接阅读原文。

自从我第一次开始学习JavaScript以来,我就一直听说React,但我承认我看了一眼,它吓坏了我。我看到一堆HTML混合了JavaScript,心想,这不是我们一直在努力避免的吗?React有什么大不了的?

相反,我只专注于学习普通JavaScript和在专业环境中使用jQuery。在尝试了几次失败的尝试之后,我终于开始使用React,我开始明白为什么我想使用React而不是普通的JS或jQuery。
我试图把我学到的一切浓缩成一个很好的介绍,与大家分享,这便是这个教程的由来。

先决条件

在你开始学习React之前,你应该事先知道一些事情。例如,如果您以前从未使用过JavaScript或DOM,那么在学习React之前,我花点精力去学习它们。
以下是我认为学习React的先决条件。
  • 基本熟悉HTML和CSS;
  • JavaScript和编程的基本知识;
  • 对DOM的基本理解;
  • 熟悉ES6语法和特性;
  • Node.js和npm已全局安装。

学习目标

了解React的基本概念和相关术语,如Babel、Webpack、JSX、组件、道具、状态和生命周期。

构建一个非常简单的React应用程序,演示上述概念。

以下是本文的源代码及Demo程序。

  • https://github.com/taniarascia/react-tutorial
  • https://taniarascia.github.io/react-tutorial

什么是React?

  • React是一个JavaScript库,是最受欢迎的库之一,GitHub上有超过100000颗星;
  • React不是一个框架(与Angular不同,Angular更固执己见);
  • React是Facebook创建的开源项目;
  • React用于在前端构建用户界面(UI);
  • React是MVC应用程序的视图层;

React最重要的一个方面是,您可以创建组件,就像自定义的、可重用的HTML元素,以快速高效地构建用户界面。React还使用state和props简化了数据的存储和处理方式。

我们将在本文中详细介绍所有这些内容,让我们开始吧。

安装React

有几种设置React的方法,这里将展示两种方法,以便您了解它的工作原理。

静态超文本文件

第一种方法并不是设置React的常用方法,也不是我们接下来的教程,但如果您曾经使用过jQuery这样的库,它会很熟悉,也很容易理解,如果您不熟悉Webpack、Babel和Node.js,这是最容易理解的入门方法。

让我们从创建一个基本的index.html文件开始。我们将在<head>内加载三个脚本:React、React DOM和Babel。我们还将使用名为root的id创建一个div,最后我们将在通常代码所在的位置创建一个script标记。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Hello React!</title>
    <script src="https://unpkg.com/react@^16/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@16.13.0/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/babel">
      // React code will go here
    </script>
  </body>
</html>

上述加载的均为撰写本文时相关库的最新稳定版本。

  • React-React顶级API(译注:React库用于创建视图)
  • React DOM-React Dom补充脚本(译注:ReactDOM库具体负责在浏览器中渲染UI)
  • Babel-一个JavaScript编译器,允许我们在旧浏览器中使用ES6+

我们的应用程序的入口点将是命名为root的div元素,它按惯例命名。您还将注意到上述代码中使用了text/babel脚本类型,这是使用babel所必需的。

现在,让我们编写React的第一个代码块。我们将使用ES6类创建一个名为App的React组件。

index.html
class App extends React.Component {
  //...
}

现在我们将添加render()方法,这是在类组件中唯一需要的方法,用于渲染DOM节点。

index.html
class App extends React.Component {
  render() {
      return (
          //...
      );
  }
}

在return中,我们将放置一个简单的HTML元素。请注意,这里没有返回字符串,因此不要在元素周围使用引号。这叫做JSX,我们很快就会了解更多。

index.html
class App extends React.Component {
  render() {
    return <h1>Hello world!</h1>
  }
}

最后,我们将使用React DOM render()方法将我们创建的App类渲染到HTML中的根div中。

index.html
ReactDOM.render(<App />, document.getElementById('root'))

下面是index.html文件的全貌:

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />

    <title>Hello React!</title>

    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
  </head>

  <body>
    <div id="root"></div>

    <script type="text/babel">class App extends React.Component {
        render() {
          return <h1>Hello world!</h1>
        }
      }

      ReactDOM.render(<App />, document.getElementById('root'))</script>
  </body>
</html>

现在,如果您在浏览器中查看index.html,您将看到我们创建的h1标记渲染到了DOM里面。
Screen Shot 2018 08 18 at 10 34 09 AM
现在我们已经完成了index.html,我们可以看到React并没有那么可怕。它只是一些JavaScript helper库,我们可以将其加载到HTML中。 我们这样做是为了演示,但从下面开始,我们将使用另一种方法:创建React App。

创建React App

我刚才使用的将JavaScript库加载到静态HTML页面中并动态呈现React和Babel的方法效率不高,而且很难维护。

幸运的是, Facebook 提供了 Create React App, 该工具预置了构建React应用程序所需的一切环境。它将创建一个实时的开发服务器,使用WebPack来自动编译React, JSX, ES6, CSS 文件, 并使用 ESLint 以监测和发现代码中的错误.

安装 create-react-app可在终端中运行下面的指令, 注意运行指令的位置为从项目工作目录向上一级目录.

npx create-react-app react-tutorial

安装完成后,用cd指令切换至新创建的目录并用npm start指令启动项目。

cd react-tutorial

npm start

运行该指令后,将弹出一个地址为localhost:3000 的新窗口以展示你刚刚创建的React App.

Screen Shot 2018 08 18 at 11 37 59 AM

Create React App非常适合初学者和大型企业应用程序的入门,但它并不适合所有场景。您可以为React创建自己的Webpack设置。

你可以查看项目目录,你将看到一个 /public 和 /src 目录,此外还有 node_modules目录, 有.gitignoreREADME.md, 和 package.json.

/public中, 一个重要的文件是 index.html, 该文件和我们前面创建的仅仅有一个root div的静态html文件非常相似。这次,我们没有加载任何的库和脚本。在 /src 目录中包含了所有的React代码。

要查看环境如何自动编译和更新React代码,请在/src/App.js中找到如下行:

To get started, edit `src/App.js` and save to reload.

并将其替换为其他文本。保存文件后,您将注意到localhost:3000使用新数据进行编译和刷新。

继续删除/src 目录中的所有文件,我们将创建自己的样板文件而不会有其他冗余文件。我们只保留index.css 和 index.js

对于index.css,我只是将Primitive css【译者注:此处的Primitive css是指Primitive UI,Primitive UI是一个用Sass构建的front-end设计工具包,用于开发响应式web应用程序。Primitive还为默认的HTML元素(按钮、表单、表、列表和排版)提供了有用的browser-consistent样式。地址参见:https://unpkg.com/primitive-ui/dist/css/main.css】的内容复制并粘贴到文件中。如果你愿意,你可以使用Bootstrap或者任何你想要的CSS框架,或者什么都不用。我只是觉得工作起来更容易。

现在,在 index.js中,我们将导入 React, ReactDOM, 和  CSS 文件。

src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'

让我们再次创建App组件。之前,我们只有一个<h1>,但现在我也添加了一个带有类的div元素。您会注意到我们使用className而不是class。这是我们的第一个提示,这里编写的代码是JavaScript,而不是HTML。

src/index.js
class App extends React.Component {
  render() {
    return (
      <div className="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}

最后,和前面一样,我们将渲染App 组件到root这个div。

src/index.js
ReactDOM.render(<App />, document.getElementById('root'))

下面是我们写的 index.js的全貌。这次,我们在文件的第一行略作改动,将Component作为React的属性加载,所以在代码中我们不再需要继续扩展 React.Component。同时注意第二行中我们直接采用了import ReactDOM from ‘react-dom’。

src/index.js
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import './index.css'

class App extends Component {
  render() {
    return (
      <divclassName="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'))

如果你访问 localhost:3000,你将看到 “Hello, React!” ,和此前一样。

React 开发者工具

有一个名为React Developer Tools的扩展,它将使您在使用React时的生活更加轻松。下载React DevTools for Chrome,或您喜欢使用的任何浏览器。

安装后,当您打开DevTools时,您将看到React的选项卡。单击它,您将能够在编写组件时检查它们。您仍然可以转到Elements选项卡查看实际的DOM输出。现在看来,这似乎没什么大不了的,但随着应用程序变得越来越复杂,它将变得越来越有必要使用。

Screen Shot 2018 08 18 at 3 45 11 PM

现在我们有了开始使用React所需的所有工具和设置。

JSX: JavaScript + XML

正如您所看到的,我们在React代码中使用了类似HTML的内容,但它并不完全是HTML。这是JSX,它代表JavaScript XML。

使用JSX,我们可以编写类似HTML的内容,也可以创建和使用自己的类似XML的标记。下面是JSX分配给变量的样子。

JSX
const heading = <h1className="site-heading">Hello, React</h1>

编写React时不是强制性的必须使用JSX。也可以用createElement,createElement使用tag、属性等渲染达到与上面的JSX相同的输出。

No JSX
const heading = React.createElement('h1', { className: 'site-heading' }, 'Hello, React!')

JSX实际上更接近于JavaScript,而不是HTML,因此在编写它时需要注意一些关键区别。

  • className 被用于代替 class ,因为 class 是JavaScript的保留关键字,不能直接使用。
  • JSX的属性和方法的命名方式为驼峰命名法 – onclick 被命名为 onClick
  • 反斜杠用于结束自封闭标签 – 例如 <img />

JavaScript表达式也可以使用花括号嵌入JSX中,包括变量、函数和属性。

const name = 'Tania'
const heading = <h1>Hello, {name}</h1>

JSX比在普通JavaScript中创建和附加许多元素更容易编写和理解,这也是人们如此喜爱React的原因之一。

组件

到目前为止,我们已经创建了一个组件——App组件。React中的几乎所有一切都由组件组成,可以是类组件(class components),也可以是简单组件(simple components)。

大多数React应用程序都有很多小组件,一切都加载到main中的 App组件中。组件通常也有自己的文件, so let’s change up our project to do so.

将App类从index.js中移除,类如如下代码:

src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import './index.css'

ReactDOM.render(<App />, document.getElementById('root'))

我们将创建一个名为App.js的新文件,并将组件放入其中。

src/App.js
import React, { Component } from 'react'

class App extends Component {
  render() {
    return (
      <divclassName="App">
        <h1>Hello, React!</h1>
      </div>
    )
  }
}

export default App

我们将组件导出为App并将其加载到index.js中。将组件分离到文件中并不是强制的,但是建议这么做。

类组件

让我们创建另一个组件。我们将创建一个表。制作Table.js,并用以下数据填充。

src/Table.js
import React, { Component } from 'react'

class Table extends Component {
  render() {
    return (
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Job</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Charlie</td>
            <td>Janitor</td>
          </tr>
          <tr>
            <td>Mac</td>
            <td>Bouncer</td>
          </tr>
          <tr>
            <td>Dee</td>
            <td>Aspiring actress</td>
          </tr>
          <tr>
            <td>Dennis</td>
            <td>Bartender</td>
          </tr>
        </tbody>
      </table>
    )
  }
}

export default Table

我们创建的这个组件是一个自定义类组件。我们将自定义组件的名字首字母大写,以区别于常规HTML元素。回到App.js中,我们可以首先将Table组件导入到App.js中:

src/App.js
import Table from './Table'

然后将其加载到App的render()中,在那里我们可以看到“你好,React!”。此外,还更改了外部容器的类。

src/App.js
import React, { Component } from 'react'
import Table from './Table'

class App extends Component {
  render() {
    return (
      <div className="container">
        <Table />
      </div>
    )
  }
}

export default App

如果您重新查看您的实时环境,您将看到表已加载。

Screen Shot 2018 08 18 at 6 10 55 PM

现在我们已经了解了什么是自定义类组件。我们可以反复使用这个组件。然而,由于数据是硬编码到其中的,所以目前它不会太有用。

简单组件

React中的另一种类型的组件是简单组件,它是一个函数。此组件不使用class关键字。让我们以Table为例,为它制作两个简单的组件——一个表头和一个表体。

我们将使用ES6箭头函数来创建这些简单的组件。首先是表头。

src/Table.js
const TableHeader = () => {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  )
}

然后是body部分

src/Table.js
const TableBody = () => {
  return (
    <tbody>
      <tr>
        <td>Charlie</td>
        <td>Janitor</td>
      </tr>
      <tr>
        <td>Mac</td>
        <td>Bouncer</td>
      </tr>
      <tr>
        <td>Dee</td>
        <td>Aspiring actress</td>
      </tr>
      <tr>
        <td>Dennis</td>
        <td>Bartender</td>
      </tr>
    </tbody>
  )
}

现在我们的表文件将如下所示。请注意,TableHeader和TableBody组件都在同一个文件中,并由Table类组件使用。

src/Table.js
const TableHeader = () => { ... }
const TableBody = () => { ... }

class Table extends Component {
  render() {
    return (
      <table>
        <TableHeader />
        <TableBody />
      </table>
    )
  }
}

一切都应该像以前一样。如您所见,组件可以嵌套在其他组件中,简单组件和类组件可以混合使用。

类组件必须包含render(),并且return只能返回一个父元素。

作为总结,让我们将简单组件与类组件进行比较。

简单组件
const SimpleComponent = () => {
  return <div>Example</div>
}
类组件
class ClassComponent extends Component {
  render() {
    return <div>Example</div>
  }
}

注意,如果返回包含在一行中,则不需要括号。

Props

现在,我们有一个很酷的Table组件,但数据是写死的。学习React的一个重要问题是学习它如何处理数据。React使用用被称作为props的属性和state来处理数据。现在,我们先学习props属性。

首先,让我们从TableBody组件中删除所有数据。

src/Table.js
const TableBody = () => {
  return <tbody/>
}

然后,让我们将所有数据移动到一个对象数组中,就像我们引入了一个基于JSON的API一样。我们必须在render()中创建这个数组。

src/App.js
class App extends Component {
  render() {
    const characters = [
      {
        name: 'Charlie',
        job: 'Janitor',
      },
      {
        name: 'Mac',
        job: 'Bouncer',
      },
      {
        name: 'Dee',
        job: 'Aspring actress',
      },
      {
        name: 'Dennis',
        job: 'Bartender',
      },
    ]

    return (
      <divclassName="container">
        <Table />
      </div>
    )
  }
}

现在,我们将把数据传递给带有属性的子组件(Table),就像使用data-属性传递数据一样。我们可以任意调用属性,只要它不是保留关键字,所以我们将使用characterData,传递的数据是characters 变量。注意,需要在characters变量周围加上大括号,因为它是一个JavaScript表达式。

src/App.js
return (
  <divclassName="container">
    <Table characterData={characters} />
  </div>
)

现在数据被传递到了Table,我们必须将它从Table传递到TableBody。

src/Table.js
class Table extends Component {
  render() {
    const { characterData } = this.props

    return (
      <table>
        <TableHeader />
        <TableBody characterData={characterData} />
      </table>
    )
  }
}

如果打开React DevTools并检查Table组件,您将看到属性中的数据数组。存储在这里的数据被称为虚拟DOM,这是一种将数据与实际DOM同步的快速有效的方法。

Screen Shot 2018 08 19 at 5 43 39 PM

不过,这些数据还不在实际的DOM中。在表中,我们可以通过this.props访问所有的props。我们只传递了一个props,characterData,因此我们将使用this.props.characterData来检索该数据。

我将使用ES6属性速记来创建一个包含this.props.characterData的变量。

const { characterData } = this.props

由于我们的Table组件实际上由两个较小的简单组件组成,我们将再次通过props将其传递给TableBody。

src/Table.js
class Table extends Component {
  render() {
    const { characterData } = this.props

    return (
      <table>
        <TableHeader />
        <TableBody characterData={characterData} />
      </table>
    )
  }
}

但是目前的TableBody还不能接受任何参数,只返回一个标记。如下面代码。我们需要改进它。

src/Table.js
const TableBody = () => {
  return <tbody/>
}

我们将把props作为参数传递,并映射到数组中,为数组中的每个对象返回一个表行。该映射将包含在rows变量中,我们将作为表达式返回该变量。

src/Table.js
const TableBody = (props) => {
  const rows = props.characterData.map((row, index) => {
    return (
      <trkey={index}>
        <td>{row.name}</td>
        <td>{row.job}</td>
      </tr>
    )
  })

  return <tbody>{rows}</tbody>
}

如果您查看应用程序的前端,所有数据都已经能够正常显示了。

您会注意到我为每个表行添加了一个键索引。在React中制作列表时,您应该始终使用键,因为它们有助于识别每个列表项。我们还将看到,当我们想要操作列表项时,这是如何必要的。

props是将现有数据传递给React组件的有效方法,但是组件不能更改props-它们是只读的。在下一节中,我们将学习如何使用stat来进一步控制React中的数据处理。

State

现在,我们将数据存储在变量的数组中,并将其作为props进行传递。这是一个很好的开始,但是想象一下如果我们想从数组中删除一个项,props这种机制会变得不适应这个场景。使用props,我们将能处理单向数据流,但使用state,我们可以从组件更新私有数据。

您可以将stat视为应保存和修改的任何数据,而不必将其添加到数据库中,例如,在确认购买之前从购物车中添加和删除项目。

首先,我们将创建一个stat对象。

src/App.js
class App extends Component {
  state = {}
}

stat对象可以存储任何你想要存储的属性。在这个例子中,我们存储了 characters 。

src/App.js
class App extends Component {
  state = {
    characters: [],
  }
}

我们将前面创建的整个对象数组移动到state.characters中。

src/App.js
class App extends Component {
  state = {
    characters: [
      {
        name: 'Charlie',
        // the rest of the data
      },
    ],
  }
}

我们的数据现在已经移到这个stat中了。由于我们希望能够从表中删除一个字符,因此我们将在其App类上创建一个removeCharacter方法。

要检索stat,我们将使用与之前相同的ES6方法获取this.state.characters。要更新stat,我们将使用this.setState(),这是一种内置的状态操作方法。我们将根据传递的索引过滤数组,并返回新数组。

必须使用this.setState()修改数组。简单地向this.state.properties应用一个新值是行不通的。

src/App.js
removeCharacter = (index) => {
  const { characters } = this.state

  this.setState({
    characters: characters.filter((character, i) => {
      return i !== index
    }),
  })
}

在setState中,我们使用filter创建一个新的数组(filter does not mutate but rather creates a new array),这是在JavaScript中修改数组的首选方法。我们这个方法是测试一个索引与数组中的所有索引,并返回除传递的索引之外的所有索引。

现在我们必须将该函数传递给组件,并在每个可以调用该函数的角色旁边呈现一个按钮。我们将把removeCharacter函数作为props传递给Table。

src/App.js
render() {
  const { characters } = this.state

  return (
    <divclassName="container">
      <Table characterData={characters} removeCharacter={this.removeCharacter} />
    </div>
  )
}

因为我们要将它从表传递到TableBody,所以我们必须将它作为一个道具再次传递,就像我们处理角色数据一样。

此外,由于我们的项目中只有App和Form两个组件有自己的状态,因此最好将Table从当前的类组件转换为一个简单的组件。

src/Table.js
const Table = (props) => {
  const { characterData, removeCharacter } = props

  return (
    <table>
      <TableHeader />
      <TableBody characterData={characterData} removeCharacter={removeCharacter} />
    </table>
  )
}

这里是我们在removeCharacter()方法中定义的索引所在的位置。在TableBody组件中,我们将传递键/索引作为参数,这样过滤器函数就知道要删除哪个项。我们将创建一个带有onClick的按钮并将其传递。

src/Table.js
<tr key={index}>
  <td>{row.name}</td>
  <td>{row.job}</td>
  <td>
    <buttononClick={() => props.removeCharacter(index)}>Delete</button>
  </td>
</tr>

onClick函数必须通过返回removeCharacter()方法的函数,否则它将尝试自动运行。

现在我们有了删除按钮,我们可以通过删除字符来修改状态。

Screen Shot 2018 08 19 at 6 37 09 PM

在上图中,我删除了Mac。

现在您应该了解Stat是如何初始化的,以及如何修改它。

提交表单数据

现在,数据存储在state中,我们可以从state中删除任何项。然而,如果我们希望能够向状态中添加新数据,该怎么办?在现实世界的应用程序中,您更可能从空状态开始并添加到其中,例如使用待办事项列表或购物车。

在做任何其他事情之前,让我们从state.characters中删除所有写死的数据,因为我们现在将通过表单更新这些数据。

src/App.js
class App extends Component {
  state = {
    characters: [],
  }
}

现在,让我们继续在名为Form.js的新文件中创建一个Form组件。

我们将Form的初始状态设置为一个具有一些空属性的对象,并将该初始状态赋给this.state。

src/Form.js
import React, { Component } from 'react'

class Form extends Component {
  initialState = {
    name: '',
    job: '',
  }

  state = this.initialState
}

以前,需要在React类组件中包含constructor(),但现在不再需要了。

我们对该表单的目标是,每当表单中的字段发生更改时,都会更新表单的状态,当我们提交时,所有数据都会传递到App状态,然后App状态会更新表。

首先,我们将创建每次对输入进行更改时都会运行的函数。事件将被传递,我们将设置Form的状态,使其具有输入的名称(键)和值。

src/Form.js
handleChange = (event) => {
  const { name, value } = event.target

  this.setState({
    [name]: value,
  })
}

在提交表单之前先完成这项工作。在呈现中,让我们从状态中获取两个数据项,并将它们作为对应于适当表单键的值进行赋值。我们将运行handleChange() 方法作为输入的onChange,最后导出Form组件。

src/Form.js
render() {
  const { name, job } = this.state;

  return (
    <form>
      <labelhtmlFor="name">Name</label>
      <inputtype="text"
        name="name"
        id="name"
        value={name}
        onChange={this.handleChange} />
      <labelhtmlFor="job">Job</label>
      <inputtype="text"
        name="job"
        id="job"
        value={job}
        onChange={this.handleChange} />
    </form>
  );
}

export default Form;

在App.js中,我们可以渲染表下的表单。

src/App.js
import Form from './Form'
src/App.js
return (
  <divclassName="container">
    <Table characterData={characters} removeCharacter={this.removeCharacter} />
    <Form />
  </div>
)

现在,如果我们转到应用程序的前端,我们将看到一个尚未提交的表单。更新一些字段,您将看到表单的本地状态正在更新。

Screen Shot 2018 08 19 at 7 55 56 PM

 

最后一步是允许我们实际提交数据并更新父状态。我们将在App上创建一个名为handleSubmit()的函数,该函数将通过使用现有的this.state.characters并使用ES6扩展运算符添加新的字符参数来更新状态。

src/App.js
handleSubmit = (character) => {
  this.setState({ characters: [...this.state.characters, character] })
}

让我们确保将其作为Form上的参数传递。

<Form handleSubmit={this.handleSubmit} />

现在在Form中,我们将创建一个名为submitForm()的方法,该方法将调用该函数,并将Form状态作为前面定义的字符参数传递。它还会将状态重置为初始状态,以便在提交后清除表单。

src/Form.js
submitForm = () => {
  this.props.handleSubmit(this.state)
  this.setState(this.initialState)
}

最后,我们将添加一个提交按钮来提交表单。我们使用的是onClick而不是onSubmit,因为我们没有使用标准的提交功能。单击将调用我们刚刚创建的submitForm。

<inputtype="button" value="Submit" onClick={this.submitForm} />

就这样!应用程序已完成。我们可以从表中创建、添加和删除用户。由于Table和TableBody已经从状态中提取数据,因此它将正确显示。

Screen Shot 2018 08 19 at 9 33 59 PM

 

这个链接是其全部代码: the complete source on GitHub.

获取API中的数据

React的一个非常常见的用法是从API获取数据。如果您不熟悉什么是API或如何连接到API,我建议您阅读《 How to Connect to an API with JavaScript》,该书将指导您了解什么是API以及如何使用普通JavaScript。

作为一个小测试,我们可以创建一个新的Api.js文件,并在其中创建新的应用程序。我们可以测试的一个公共API是Wikipedia API(Wikipedia API),我在这里有一个URL端点(URL endpoint right here )用于随机搜索。您可以转到该链接查看API,并确保浏览器上安装了JSONView(JSONView)。

我们将使用JavaScript的内置Fetch从该URL端点收集数据并显示它。您只需更改index.js中的URL,即可在我们创建的应用程序和此测试文件之间进行切换-从’./Api’导入应用程序;。

我不打算逐行解释这段代码,因为我们已经了解了如何通过状态数组创建组件、渲染和映射。这段代码的新方面是componentDidMount(),一种React生命周期方法。生命周期是React中调用方法的顺序。Mounting指的是插入到DOM中的项。

当我们引入API数据时,我们希望使用componentDidMount,因为我们希望在引入数据之前确保组件已呈现给DOM。在下面的片段中,您将看到我们如何从Wikipedia API引入数据,并将其显示在页面上

Api.js
import React, { Component } from 'react'

class App extends Component {
  state = {
    data: [],
  }

  // Code is invoked after the component is mounted/inserted into the DOM tree.
  componentDidMount() {
    const url =
      'https://en.wikipedia.org/w/api.php?action=opensearch&search=Seona+Dancing&format=json&origin=*'

    fetch(url)
      .then((result) => result.json())
      .then((result) => {
        this.setState({
          data: result,
        })
      })
  }

  render() {
    const { data } = this.state

    const result = data.map((entry, index) => {
      return <likey={index}>{entry}</li>
    })

    return <ul>{result}</ul>
  }
}

export default App

在本地服务器中保存并运行此文件后,您将看到DOM中显示的Wikipedia API数据。

Screen Shot 2018 08 19 at 10 12 41 PM

 

还有其他生命周期方法,但对它们的研究将超出本文的范围。您可以在这里(read more about React components here.)阅读更多关于React组件的信息。

*维基百科的搜索选择可能不是随机的。这可能是我在2005年率先发表的一篇文章。

构建和部署React应用程序

到目前为止,我们所做的一切都是在开发环境中完成的。我们一直在进行编译、动态重新加载和动态更新。对于生产环境,我们希望加载静态文件,而不是源代码。我们可以通过构建并部署它来做到这一点。

现在,如果您只想编译所有React代码并将其放在某个目录的根目录中,那么只需运行以下指令:

npm run build

这将创建一个包含应用程序的build文件夹。把文件夹的内容放在任何地方(如网站的根目录),你就完成了React应用程序的部署工作!

我们还可以更进一步,让npm为我们部署。我们将构建GitHub页面,因此您必须熟悉Git(be familiar with Git )并在GitHub上编写代码。

确保您已退出本地React环境,因此代码当前未运行。首先,我们将向package.json添加一个主页字段,该字段包含我们希望我们的应用程序使用的URL。

package.json
"homepage": "https://taniarascia.github.io/react-tutorial",

我们还将向scripts属性添加这两行。

"scripts": {
  // ...
  "predeploy": "npm run build",
  "deploy": "gh-pages -d build"
}

在项目中,您将向devDependencies添加gh-pages。

npm install --save-dev gh-pages

我们将创建build,它将包含所有已编译的静态文件。

npm run build

最后,我们将部署到gh-pages。

npm run deploy

现在我们完成了这个项目! 这个项目可以在这个网址访问: https://taniarascia.github.io/react-tutorial.

总结

这篇文章应该向您介绍了React、简单组件和类组件、状态、属性、处理表单数据、从API获取数据以及部署应用程序。使用React还有很多需要学习和做的事情,但我希望你现在能自信地钻研和使用React。

如果有什么不清楚的地方,或者你想在本文或后续文章中看到什么,请告诉我。

如果觉得本文翻译得不合适的地方,请发邮件给dragon#txeet.com(请手动将#替换成@)。