Interested in learning React? Get my React Handbook
有兴趣学习React吗? 获取我的React手册
React is a JavaScript library that aims to simplify the development of visual interfaces.
React是一个JavaScript库,旨在简化可视界面的开发。
Developed at Facebook and released to the world in 2013, it drives some of the most widely used code in the world. It powers Facebook and Instagram among many, many other software companies.
它是在Facebook上开发并于2013年发布的,它驱动了一些世界上使用最广泛的代码。 它为许多其他软件公司中的Facebook和Instagram提供动力。
Its primary goal is to make it easy to reason about an interface and its state at any point in time by dividing the UI into a collection of components.
它的主要目标是通过将UI划分为组件集合,从而在任何时间点都可以轻松地推断出接口及其状态。
React is used to build single-page web applications, along with many other libraries and frameworks that were available before React came to life.
React用于构建单页Web应用程序,以及React诞生之前可用的许多其他库和框架。
React has taken the frontend web development world by storm. Why?
React已经席卷了前端Web开发领域。 为什么?
At the time when React was announced, Ember.js and Angular 1.x were the predominant choices for frameworks. Both of these imposed too many conventions on the code so that porting an existing app was not convenient at all.
在React宣布之时,Ember.js和Angular 1.x是框架的主要选择。 两者都在代码上施加了太多约定,因此移植现有应用程序根本不方便。
React was created to be very easy to integrate into an existing project. That’s how they had to do it at Facebook in order to introduce it to the existing codebase. Also, those two frameworks brought too much to the table, while React only chose to implement the View layer instead of the full MVC stack.
React的创建非常易于集成到现有项目中。 这就是他们必须在Facebook上这样做的目的,以便将其引入现有的代码库中。 另外,这两个框架给表带来了太多的麻烦,而React只选择实现视图层而不是完整的MVC堆栈。
At that same time, Angular 2.x was announced by Google, along with the backwards incompatibility and major changes it was going to bring. Moving from Angular 1 to 2 was like moving to a different framework. And so this fact, along with the execution speed improvements that React promised, made React something developers were eager to try.
与此同时,Google宣布了Angular 2.x,以及向后的不兼容和即将带来的重大变化。 从Angular 1迁移到2就像迁移到其他框架。 因此,这个事实以及React承诺的执行速度改进,使React成为开发人员渴望尝试的东西。
Being backed by Facebook benefits a project if it turns out to be successful. But it’s not a guarantee, and there are many failed open source projects by both Facebook and Google (among others).
如果事实证明是成功的话,得到Facebook的支持会使项目受益。 但这不是保证,而且Facebook和Google(还有其他许多公司)都有许多失败的开源项目。
Even though I said that React is simpler than alternative frameworks, diving into React is still complex. This is mostly because of the corollary technologies that can be integrated with React, like Redux, Relay or GraphQL.
尽管我说过React比其他框架要简单,但是深入React仍然很复杂。 这主要是因为可以与React集成的推论技术,例如Redux,Relay或GraphQL。
React in itself has a very small API.
React本身具有非常小的API。
There isn’t much more in React other than these concepts:
除了这些概念,React中没有什么比其他更多的了:
We’ll see each one of them in my next articles.
我们将在下一篇文章中看到其中的每一个。
Many developers, including myself, at first sight thought that JSX was horrible, and quickly dismissed React.
包括我自己在内的许多开发人员乍一看都认为JSX太可怕了,并Swift解雇了React。
Even though they said JSX was not required, using React without JSX was painful.
即使他们说不需要JSX,但在没有JSX的情况下使用React也很痛苦。
It took me a couple years of occasionally looking at it to start digesting JSX, and now I largely prefer it over the alternative (that is, using templates).
我花了几年的时间偶尔看一下它,才开始消化JSX,现在,我比替代方法(即使用模板)更喜欢它。
The major benefit of using JSX is that you’re only interacting with JavaScript objects, not template strings.
使用JSX的主要好处是,您仅与JavaScript对象进行交互,而不与模板字符串进行交互。
JSX is not embedded HTML.
JSX不是嵌入式HTML。
Many tutorials for React beginners like to postpone the introduction of JSX for later, because they assume the reader would be better off without it. Since I am now a JSX fan, however, I’ll immediately jump into it.
许多针对React初学者的教程都希望将JSX的引入推迟到以后,因为他们认为没有JSX会更好。 由于我现在是JSX迷,因此,我将立即加入其中。
Here is how you define a h1 tag containing a string:
这是定义包含字符串的h1标签的方法:
const element = <h1>Hello, world!</h1>
It looks like a strange mix of JavaScript and HTML, but in reality it’s all JavaScript.
它看起来像是JavaScript和HTML的奇怪组合,但实际上是JavaScript。
What looks like HTML is actually a sugar syntax for defining components and their positioning inside the markup.
看起来像HTML的实际上是一种糖语法,用于定义组件及其在标记内的位置。
Inside a JSX expression, attributes can be inserted very easily:
在JSX表达式中,可以很容易地插入属性:
const myId = 'test' const element = <h1 id={myId}>Hello, world!</h1>
You just need to pay attention to when an attribute has a dash (-
), which is converted to camelCase syntax instead, as well as to these two special cases:
您只需要注意属性何时带有破折号( -
)(而不是转换为camelCase语法)以及以下两种特殊情况:
class
becomes className
class
成为className
for
becomes htmlFor
for
htmlFor
because they are reserved words in JavaScript.
因为它们是JavaScript中的保留字。
Here’s a JSX snippet that wraps two components into a div
tag:
这是一个JSX片段,将两个组件包装到div
标签中:
<div> <BlogPostsList /> <Sidebar /> </div>
A tag always needs to be closed, because this is more XML than HTML (if you remember the XHTML days, this will be familiar, but since then the HTML5 loose syntax won). In this case, a self-closing tag is used.
始终需要关闭标签,因为XML比HTML还要多(如果您还记得XHTML的日子,那会很熟悉,但是从那时起,HTML5宽松的语法就赢了)。 在这种情况下,使用自动关闭标签。
JSX, when introduced with React, is no longer a React-only technology.
JSX与React一起引入时,不再是仅React技术。
A component is one isolated piece of the interface. For example, in a typical blog homepage, you might find the Sidebar component and the Blog Posts List component. They are in turn composed by components themselves, so you could have a list of Blog post components, each for every blog post, and each with its own peculiar properties.
组件是接口的一个孤立部分。 例如,在典型的博客主页中,您可能会找到侧边栏组件和“博客帖子列表”组件。 它们又由组件本身组成,因此您可以拥有一个博客帖子组件列表,每个组件用于每个博客帖子,并且每个组件都有其独特的属性。
React makes it very simple: everything is a component.
React使它非常简单:一切都是组件。
Even plain HTML tags are components on their own, and they are added by default.
甚至纯HTML标记本身都是组件,默认情况下会添加它们。
The next two lines are equivalent — they do the same thing. One with JSX, one without, by injecting <h1>Hello World
!</h1> into an element
with id app.
接下来的两行是等效的-它们执行相同的操作。 一个与JSX,一个没有,通过注射<h1>Hello World
!</ h1>成ELEM ent
ID为应用程序。
import React from 'react' import ReactDOM from 'react-dom'
ReactDOM.render( <h1>Hello World!</h1>, document.getElementById('app') )
ReactDOM.render( React.DOM.h1(null, "Hello World!"), document.getElementById('app') )
See, React.DOM
exposed for us an h1
component. Which other HTML tags are available? All of them! You can inspect what React.DOM
offers by typing it in the Browser Console:
看到, React.DOM
为我们公开了一个h1
组件。 还有哪些其他HTML标记? 他们全部! 您可以通过在浏览器控制台中键入来检查React.DOM
提供的内容:
(the list goes on…)
(列表继续…)
The built-in components are nice, but you’ll quickly outgrow them. What React excels at is letting us compose a UI by composing custom components.
内置组件不错,但是您很快就会将它们淘汰。 React擅长的是让我们通过组成自定义组件来组成UI。
There are 2 ways to define a component in React:
有两种在React中定义组件的方法:
A stateless component does not manage internal state, and is just a function:
无状态组件不管理内部状态,而仅仅是一个功能:
const BlogPostExcerpt = () => { return ( <div> <h1>Title</h1> <p>Description</p> </div> ) }
A stateful component is a class, which manages state in its own properties:
有状态组件是一个类,它通过自己的属性管理状态:
import React, { Component } from 'react'
class BlogPostExcerpt extends Component { render() { return ( <div> <h1>Title</h1> <p>Description</p>; </div> ) } }
As they stand, they are equivalent because there is no state management yet (coming in the next couple articles).
按照它们的立场,它们是等效的,因为还没有状态管理(将在接下来的几篇文章中介绍)。
There is a third syntax which uses the ES5
/ ES2015
syntax without the classes:
第三种语法使用不带类的ES5
/ ES2015
语法:
import React from 'react'
React.createClass({ render() { return ( <div> <h1>Title</h1> <p>Description</p> </div> ) } })
You’ll rarely see this in modern >
ES6 codebases.
在现代>
ES6代码库中,您几乎看不到这一点。
Props is how Components get their properties. Starting from the top component, every child component gets its props from the parent. In a stateless component, props is all that gets passed, and they are available by adding props
as the function argument:
道具是组件如何获取其属性的方法。 从顶部组件开始,每个子组件都从父组件获取其道具。 在无状态组件中,props是传递的所有东西,可以通过将props
作为函数参数添加来使用它们:
const BlogPostExcerpt = (props) => { return ( <div> <h1>{props.title}</h1> <p>{props.description}</p> </div> ) }
In a stateful component, props are passed by default. There is no need to add anything special, and they are accessible as this.props
in a Component instance.
在有状态组件中,默认情况下会传递道具。 无需添加任何特殊内容,它们可以作为Component实例中的this.props
访问。
import React, { Component } from 'react'
class BlogPostExcerpt extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.description}</p>; </div> ) } }
Since JavaScript is a dynamically typed language, we don’t really have a way to enforce the type of a variable at compile time. If we pass invalid types, they will fail at runtime or give weird results if the types are compatible but not what we expect.
由于JavaScript是一种动态类型化的语言,因此我们实际上没有办法在编译时强制执行变量的类型。 如果我们传递无效的类型,则这些类型将在运行时失败,或者如果这些类型兼容但不是我们期望的结果,则会给出奇怪的结果。
Flow and TypeScript help a lot, but React has a way to directly help with props types. Even before running the code, our tools (editors, linters) can detect when we are passing the wrong values:
Flow和TypeScript有很多帮助,但是React可以直接帮助道具类型。 即使在运行代码之前,我们的工具(编辑器,lints)也可以检测到何时传递了错误的值:
import PropTypes from 'prop-types'; import React from 'react'
class BlogPostExcerpt extends Component { render() { return ( <div> <h1>{this.props.title}</h1> <p>{this.props.description}</p> </div> ) } }
BlogPostExcerpt.propTypes = { title: PropTypes.string, description: PropTypes.string };
export default BlogPostExcerpt
These are the fundamental types we can accept:
这些是我们可以接受的基本类型:
We can accept one of two types:
我们可以接受以下两种类型之一:
PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
We can accept one of many values:
我们可以接受许多值之一:
PropTypes.oneOf(['Test1', 'Test2']),
We can accept an instance of a class:
我们可以接受一个类的实例:
PropTypes.instanceOf(Something)
We can accept any React node:
我们可以接受任何React节点:
PropTypes.node
or even any type at all:
甚至根本没有任何类型:
PropTypes.any
Arrays have a special syntax that we can use to accept an array of a particular type:
数组具有一种特殊的语法,我们可以使用它来接受特定类型的数组:
PropTypes.arrayOf(PropTypes.string)
We can compose an object property by using:
我们可以使用以下方法来组成对象属性:
PropTypes.shape({ color: PropTypes.string, fontSize: PropTypes.number })
Appending isRequired
to any PropTypes option will cause React to return an error if that property is missing:
附加isRequired
任何PropTypes选项将导致作出React,如果该属性是缺少返回一个错误:
PropTypes.arrayOf(PropTypes.string).isRequired, PropTypes.string.isRequired,
If any value is not required, we need to specify a default value for it if it’s missing when the Component is initialized.
如果不需要任何值,则在初始化组件时如果缺少默认值,则需要为其指定默认值。
BlogPostExcerpt.propTypes = { title: PropTypes.string, description: PropTypes.string }
BlogPostExcerpt.defaultProps = { title: '', description: '' }
Some tooling, like ESLint, has the ability to enforce defining the defaultProps for a Component with some propTypes not explicitly required.
某些工具(如ESLint)可以强制为某些组件(没有明确要求的propType)定义defaultProps。
When initializing a component, pass the props in a way similar to HTML attributes:
初始化组件时,以类似于HTML属性的方式传递道具:
const desc = 'A description' //... <BlogPostExcerpt title="A blog post" description={desc} />
We passed the title as a plain string (something we can only do with strings!), and the description as a variable.
我们将标题作为纯字符串( 只能使用字符串!)进行传递,将描述作为变量传递。
A special prop is children
. That contains the value of anything that is passed in the body
of the component. For example:
一个特殊的道具是children
。 它包含在组件body
中传递的任何值。 例如:
<BlogPostExcerpt title="A blog post" description={desc}> Something </BlogPostExcerpt>
In this case, inside BlogPostExcerpt
we could access “Something” by looking up this.props.children
.
在这种情况下,我们可以在BlogPostExcerpt
内部通过查找this.props.children
来访问“ Something”。
While Props allow a Component to receive properties from its parent (they could be “instructed” to print some data for example), state allows a component to take on a life of its own, and be independent from the surrounding environment.
尽管道具允许组件从其父对象接收属性(例如,可以“指示”它们打印一些数据),但状态允许组件承担其自身的生命,并且独立于周围环境。
Remember: only class-based Components can have a state. So if you need to manage state in a stateless (function-based) Component, you first need to “upgrade” it to a Class component:
请记住:只有基于类的组件才能具有状态。 因此,如果您需要在无状态(基于功能)的组件中管理状态,则首先需要将其“升级”到Class组件:
const BlogPostExcerpt = () => { return ( <div> <h1>Title</h1> <p>Description</p> </div> )}
becomes:
变成:
import React, { Component } from 'react'
class BlogPostExcerpt extends Component { render() { return ( <div> <h1>Title</h1> <p>Description</p> </div> ) } }
In the Component constructor, initialize this.state
. For example, the BlogPostExcerpt component might have a clicked
state:
在Component构造函数中,初始化this.state
。 例如,BlogPostExcerpt组件可能具有clicked
状态:
class BlogPostExcerpt extends Component {
constructor(props) { super(props) this.state = { clicked: false } }
render() { return ( <div> <h1>Title</h1> <p>Description</p>; </div> ) } }
The clicked state can be accessed by referencing this.state.clicked
:
可以通过引用this.state.clicked
来访问clicked状态:
class BlogPostExcerpt extends Component { constructor(props) { super(props) this.state = { clicked: false } }
render() { return ( <div> <h1>Title</h1> <p>Description</p> <p>Clicked: {this.state.clicked}</p> </div> ) } }
A state should never be mutated by using
绝对不能通过使用来改变状态
this.state.clicked = true
Instead, you should always use setState()
instead, passing it as an object:
相反,您应该始终使用setState()
,并将其作为对象传递:
this.setState({ clicked: true })
The object can contain a subset, or a superset, of the state. Only the properties you pass will be mutated. The ones omitted will be left in their current state.
对象可以包含状态的子集或超集。 只有您传递的属性会发生突变。 省略的将保留其当前状态。
setState()
(Why you should always use setState()
)The reason is that using this method, React knows that the state has changed. It will then start the series of events that will lead to the Component being re-rendered, along with any DOM updates.
原因是使用此方法,React知道状态已更改。 然后它将开始一系列事件,这些事件将导致重新渲染组件以及任何DOM更新。
A parent of a Component cannot tell if the child is stateful or stateless. The same goes for children of a Component.
Component的父级无法确定子级是有状态还是无状态。 组件的子代也是如此。
Being stateful or stateless (functional or class-based) is entirely an implementation detail that other components don’t need to care about.
有状态或无状态(基于功能或基于类)完全是其他组件不需要关心的实现细节。
This leads us to Unidirectional Data Flow
这导致我们进入单向数据流
A state is always owned by one Component. Any data that’s affected by this state can only affect Components below it: its children.
状态始终由一个组件拥有。 受此状态影响的任何数据只能影响其下的组件:其子组件。
Changing a state on a Component will never affect its parent, or its siblings, or any other Component in the application — just its children.
更改组件上的状态永远不会影响其父项,其兄弟姐妹或应用程序中的任何其他组件-仅影响其子级。
This is the reason that, many times, the state is moved up in the Components tree.
这是很多时候该状态在“组件”树中上移的原因。
Because of the Unidirectional Data Flow rules, if two components need to share a state, the state needs to be moved up to a common ancestor.
由于单向数据流规则,如果两个组件需要共享一个状态,则需要将该状态上移到一个共同的祖先。
Often, the closest ancestor is the best place to manage the state, but it’s not a mandatory rule.
通常,最接近的祖先是管理国家的最佳场所,但这不是强制性规则。
The state is passed down to the components that need that value via props:
该状态通过props传递给需要该值的组件:
class Converter extends React.Component { constructor(props) { super(props) this.state = { currency: '€' } }
render() { return ( <div> <Display currency={this.state.currency} /> <CurrencySwitcher currency={this.state.currency} /> <;/div> ) } }
The state can be mutated by a child component by passing a mutating function down as a prop:
子组件可以通过将mutating函数作为prop向下传递来改变状态:
class Converter extends React.Component { constructor(props) { super(props) this.state = { currency: '€' } }
handleChangeCurrency = (event) => { this.setState({ currency: this.state.currency === '€' ? '$' : '€' }) }
render() { return ( <div> <Display currency={this.state.currency} /> <CurrencySwitcher currency={this.state.currency} handleChangeCurrency={this.handleChangeCurrency} /> </div> ) } }
const CurrencySwitcher = (props) => { return ( <button onClick={props.handleChangeCurrency}> Current currency is {props.currency}. Change it! </button> ) }
const Display = (props) => { return ( <p>Current currency is {props.currency}.<;/p> ) }
React provides an easy way to manage events. Prepare to say goodbye to addEventListener
:)
React提供了一种简单的方法来管理事件。 准备告别addEventListener
:)
In the previous article about the State you saw this example:
在上一篇关于国家的文章中,您看到了以下示例:
const CurrencySwitcher = (props) => { return ( <button onClick={props.handleChangeCurrency}> Current currency is {props.currency}. Change it! </button> ) }
If you’ve been using JavaScript for a while, this is just like plain old JavaScript event handlers. But this time you’re defining everything in JavaScript, not in your HTML, and you’re passing a function, not a string.
如果您已经使用JavaScript一段时间了,则就像普通的旧式JavaScript事件处理程序一样。 但是这次您要用JavaScript而不是HTML定义所有内容,并且要传递一个函数而不是字符串。
The actual event names are a little bit different, because in React you use camelCase for everything. So onclick
becomes onClick
, onsubmit
becomes onSubmit
.
实际的事件名称有些不同,因为在React中,您将camelCase用于所有内容。 所以onclick
变成onClick
, onsubmit
变成onSubmit
。
For reference, this is old school HTML with JavaScript events mixed in:
作为参考,这是旧式HTML,其中混合了JavaScript事件:
<button onclick="handleChangeCurrency()"> ... <;/button>
It’s a convention to have event handlers defined as methods on the Component class:
将事件处理程序定义为Component类的方法是一种惯例:
class Converter extends React.Component { handleChangeCurrency = (event) => { this.setState({ currency: this.state.currency === '€' ? '$' : '€' }) } }
All handlers receive an event object that adheres, cross-browser, to the W3C UI Events spec.
所有处理程序都将收到一个跨浏览器遵守W3C UI Events规范的事件对象。
this
绑定到方法中 (Bind this
in methods)Don’t forget to bind methods. The methods of ES6 classes by default are not bound. What this means is that this
is not defined unless you define methods as
不要忘记绑定方法。 默认情况下,未绑定ES6类的方法。 这是什么意思是, this
是没有定义的,除非你定义的方法
class Converter extends React.Component { handleClick = (e) => { /* ... */ } //... }
when using the the property initializer syntax with Babel (enabled by default in create-react-app
).
与Babel一起使用属性初始值设定项语法时(默认在create-react-app
启用)。
Otherwise you need to bind it manually in the constructor:
否则,您需要在构造函数中手动将其绑定:
class Converter extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); }
handleClick(e) {} }
There are lots of events supported, so here’s a summary list.
支持许多事件,因此这里是摘要列表。
You’ll run across articles describing React as a declarative approach to building UIs.
您将遍历描述React作为构建UI的声明性方法的文章。
See declarative programming to read more about declarative programming.
请参阅声明式编程,以了解有关声明式编程的更多信息。
React made its “declarative approach” quite popular and upfront so it permeated the frontend world along with React.
React使它的“声明式方法”非常流行和前期,因此它与React一起渗透到前端世界。
It’s really not a new concept, but React made building UIs a lot more declarative than with HTML templates. You can build Web interfaces without even touching the DOM directly, and you can have an event system without having to interact with the actual DOM Events.
这实际上不是一个新概念,但是React使构建UI的声明性比使用HTML模板更具声明性。 您可以构建Web界面而无需直接接触DOM,并且可以具有事件系统而不必与实际的DOM事件进行交互。
For example, looking up elements in the DOM using jQuery or DOM events is an iterative approach.
例如,使用jQuery或DOM事件在DOM中查找元素是一种迭代方法。
React’s declarative approach abstracts that for us. We just tell React we want a component to be rendered in a specific way, and we never have to interact with the DOM to reference it later.
React的声明式方法为我们抽象了这一点。 我们只是告诉React我们希望组件以特定的方式呈现,并且我们以后不必再与DOM交互来引用它。
Many existing frameworks, before React came on the scene, were directly manipulating the DOM on every change.
在React出现之前,许多现有框架都在每次更改时直接操作DOM。
What is the DOM, first of all? The DOM (Document Object Model) is a Tree representation of the page, starting from the <ht
ml> tag, going down into each of the children, called nodes.
首先是什么DOM? DOM( 文档对象模型 )是页面的树形表示,从<ht
ml>标记开始,向下进入每个称为节点的子级。
It’s kept in the browser memory, and directly linked to what you see in a page. The DOM has an API that you can use to traverse it, access every single node, filter them, and modify them.
它保存在浏览器的内存中,并直接链接到您在页面中看到的内容。 DOM具有一个API,可用于遍历,访问每个节点,对其进行过滤和修改。
The API is the familiar syntax you have likely seen many times, if you were not using the abstract API provided by jQuery and friends:
如果您未使用jQuery和朋友提供的抽象API,则该API是您可能多次看到的熟悉语法:
document.getElementById(id) document.getElementsByTagName(name) document.createElement(name) parentNode.appendChild(node) element.innerHTML element.style.left element.setAttribute()element.getAttribute() element.addEventListener() window.content window.onload window.dump()window.scrollTo()
React keeps a copy of the DOM representation, because the Virtual DOM concerns the React rendering.
由于虚拟DOM与React渲染有关,因此React保留DOM表示的副本。
Every time the DOM changes, the browser has to do two intensive operations: repaint (visual or content changes to an element that do not affect the layout and positioning relative to other elements) and reflow (recalculate the layout of a portion of the page — or the whole page layout).
每次DOM更改时,浏览器都必须执行两项密集的操作:重新绘制(对元素的视觉或内容更改不影响相对于其他元素的布局和位置)和重排(重新计算页面一部分的布局-或整个页面的布局)。
React uses a Virtual DOM to help the browser use fewer resources when changes need to be made on a page.
当需要在页面上进行更改时,React使用虚拟DOM来帮助浏览器使用更少的资源。
When you call setState()
on a Component, specifying a state different than the previous one, React marks that Component as dirty. This is key: React only updates when a Component changes the state explicitly.
当您在Component上调用setState()
时,指定一个不同于上一个状态的状态时,React将该Component标记为dirty 。 这很关键:React仅在组件显式更改状态时更新。
What happens next is:
接下来发生的是:
React updates the Virtual DOM relative to the components marked as dirty (with some additional checks, like triggering shouldComponentUpdate()
)
React会相对于标记为脏组件的组件更新Virtual DOM(进行一些额外的检查,例如触发shouldComponentUpdate()
)
The key thing is that React batches much of the changes and performs a unique update to the real DOM. It does this by changing all the elements that need to be changed at the same time, so the repaint and reflow the browser must perform to render the changes are executed just once.
关键是React会批量处理许多更改,并对真实DOM执行唯一的更新。 它是通过同时更改所有需要更改的元素来实现的,因此浏览器必须执行的重新绘制和重排才能呈现更改,而这些更改只能执行一次。
Interested in learning React? Get my React Handbook
有兴趣学习React吗? 获取我的React手册
翻译自: https://www.freecodecamp.org/news/the-beginners-guide-to-react-9be65f50a55c/