Update: This article is now part of my book “React.js Beyond The Basics”.

更新:本文现在是我的书《超越基础的React.js》的一部分。

Read the updated version of this content and more about React at jscomplete.com/react-beyond-basics.

jscomplete.com/react-beyond-basics中阅读此内容的更新版本以及有关React的更多信息

This article is not going to cover what React is or why you should learn it. Instead, this is a practical introduction to the fundamentals of React.js for those who are already familiar with JavaScript and know the basics of the DOM API.

本文不会介绍什么是React或为什么要学习它 。 相反,这是对那些已经熟悉JavaScript并了解DOM API基础知识的人的React.js基础知识的实用介绍。

All code examples below are labeled for reference. They are purely intended to provide examples of concepts. Most of them can be written in a much better way.

以下所有代码示例均已标记为参考。 它们纯粹是为了提供概念的示例。 它们中的大多数可以用更好的方式编写。

基本原理1:React完全涉及组件 (Fundamental 1: React is all about components)

React is designed around the concept of reusable components. You define small components and you put them together to form bigger components.

React是围绕可重用​​组件的概念设计的。 您定义小组件,然后将它们放在一起以形成更大的组件。

All components small or big are reusable, even across different projects.

所有大小的组件都可以重用,即使在不同的项目中也可以重用。

A React component — in its simplest form — is a plain-old JavaScript function:

一个最简单的形式的React组件是一个普通JavaScript函数:

// Example 1
// https://jscomplete.com/repl?j=Sy3QAdKHW
function Button (props) {// Returns a DOM element here. For example:return <button type="submit">{props.label}</button>;
}
// To render the Button component to the browser
ReactDOM.render(<Button label="Save" />, mountNode)

The curly braces used for the button label are explained below. Don’t worry about them now. ReactDOM will also be explained later, but if you want to test this example and all upcoming code examples, the above render function is what you need.

下面说明用于按钮标签的花括号。 现在不用担心它们。 ReactDOM也将在后面解释,但是如果您想测试该示例以及所有即将发布的代码示例,则需要上面的render函数。

The second argument to ReactDOM.render is the destination DOM element which React is going to take over and control. In the jsComplete React Playground, you can just use the special variable mountNode.

ReactDOM.render的第二个参数是React将要接管并控制的目标DOM元素。 在jsComplete React Playground中 ,您可以仅使用特殊变量mountNode

JavaScript REPL and Playground for React.jsTest modern JavaScript and React.js code in the browser without any configurationsjscomplete.com/react

适用于React.jsJavaScript REPL和Playground 无需任何配置即可在浏览器中测试现代JavaScript和React.js代码 jscomplete.com/react

Note the following about Example 1:

请注意以下有关示例1的内容:

  • The component name starts with a capital letter. This is required since we will be dealing with a mix of HTML elements and React elements. Lowercase names are reserved for HTML elements. In fact, go ahead and try to name the React component just “button” and see how ReactDOM will ignore the function and renders a regular empty HTML button.组件名称以大写字母开头。 这是必需的,因为我们将处理HTML元素和React元素的混合。 小写名称保留给HTML元素。 实际上,继续尝试将React组件命名为“ button”,看看ReactDOM如何忽略该函数并呈现常规的空HTML按钮。
  • Every component receives a list of attributes, just like HTML elements. In React, this list is called props. With a function component, you can name it anything though.

    每个组件都会收到一个属性列表,就像HTML元素一样。 在React中,此列表称为props 。 使用功能组件,您可以为其命名。

  • We weirdly wrote what looks like HTML in the returned output of the Button function component above. This is neither JavaScript nor HTML, and it’s not even React.js. But, it’s so popular that it became the default in React applications. It’s called JSX and it’s a JavaScript extension. JSX is also a compromise! Go ahead and try and return any other HTML element inside the function above and see how they are all supported (for example, return a text input element).

    我们在上面的Button函数组件的返回输出中怪异地写了HTML。 这既不是JavaScript也不是HTML,甚至都不是React.js。 但是,它是如此流行,以至于成为了React应用程序的默认设置。 它称为JSX ,是JavaScript扩展。 JSX也是一种折衷方案 ! 继续尝试并返回上面函数内的任何其他HTML元素,并查看如何全部支持它们(例如,返回文本输入元素)。

基本原理2:JSX的作用是什么? (Fundamental 2: What the flux is JSX?)

Example 1 above can be written in pure React.js without JSX as follows:

上面的示例1可以用不带JSX的纯React.js编写,如下所示:

// Example 2 -  React component without JSX
// https://jscomplete.com/repl?j=HyiEwoYB-
function Button (props) {return React.createElement("button",{ type: "submit" },props.label);
}
// To use Button, you would do something like
ReactDOM.render(React.createElement(Button, { label: "Save" }),mountNode
);

The createElement function is the main function in the React top-level API. It’s 1 of a total of 8 things in that level that you need to learn. That’s how small the React API is.

createElement函数是React顶级API中的主要函数。 这是您需要学习的8项内容中的1项。 那就是React API的大小。

Much like the DOM itself having a document.createElement function to create an element specified by a tag name, React’s createElement function is a higher-level function that can do what document.createElement does, but it can also be used to create an element to represent a React component. We did the latter when we used the Button component in Example 2 above.

就像DOM本身具有document.createElement函数来创建由标签名指定的元素一样,React的createElement函数是一个高级函数,可以完成document.createElement工作,但是它也可以用于创建元素来代表一个React组件 当我们在上面的示例2中使用Button组件时,我们执行了后者。

Unlike document.createElement, React’s createElement accepts a dynamic number of arguments after the second one to represent the children of the created element. So createElement actually creates a tree.

document.createElement不同,React的createElement在第二个参数之后接受动态数量的参数来表示所创建元素的子代 。 因此createElement实际上会创建一棵树

Here’s an example of that:

这是一个例子:

// Example 3 -  React’s createElement API
// https://jscomplete.com/repl?j=r1GNoiFBb
const InputForm = React.createElement("form",{ target: "_blank", action: "https://google.com/search" },React.createElement("div", null, "Enter input and click Search"),React.createElement("input", { name: "q", className: "input" }),React.createElement(Button, { label: "Search" })
);
// InputForm uses the Button component, so we need that too:
function Button (props) {return React.createElement("button",{ type: "submit" },props.label);
}
// Then we can use InputForm directly with .render
ReactDOM.render(InputForm, mountNode);

Note a few things about the example above:

请注意有关上面的示例的一些注意事项:

  • InputForm is not a React component; it’s just a React element. This is why we used it directly in the ReactDOM.render call and not with <InputForm />.

    InputForm不是React组件; 它只是一个React 元素 。 这就是为什么我们直接在ReactDOM.render调用中而不是在<InputForm />中使用它的原因。

  • The React.createElement function accepted multiple arguments after the first two. Its list of arguments starting from the 3rd one comprises the list of children for the created element.

    React.createElement函数在前两个之后接受多个参数。 它的参数列表从第3个开始,包括所创建元素的子级列表。

  • We were able to nest React.createElement calls because it’s all JavaScript.

    我们能够嵌套React.createElement调用,因为它们都是JavaScript。

  • The second argument to React.createElement can be null or an empty object when no attributes or props are needed for the element.

    当元素不需要属性或道具时, React.createElement的第二个参数可以为null或为空对象。

  • We can mix HTML element with React elements.我们可以将HTML元素与React元素混合使用。
  • React’s API tries to be as close to the DOM API as possible, that’s why we use className instead of class for the input element. Secretly, we all wish the React’s API would become part of the DOM API itself. Because, you know, it’s much much better.

    React的API尝试尽可能地接近DOM API,这就是为什么我们使用className而不是class作为输入元素的原因。 秘密地,我们都希望React的API成为DOM API本身的一部分。 因为,这要好得多。

The code above is what the browser understands when you include the React library. The browser does not deal with any JSX business. However, we humans like to see and work with HTML instead of these createElement calls (imagine building a website with just document.createElement, which you can!). This is why the JSX compromise exists. Instead of writing the form above with React.createElement calls, we can write it with a syntax very similar to HTML:

上面的代码是您包含React库时浏览器可以理解的内容。 该浏览器不处理任何JSX业务。 但是,我们人类喜欢查看并使用HTML而不是使用这些createElement调用(想象只使用document.createElement构建网站!)。 这就是为什么存在JSX折衷的原因。 不用使用React.createElement调用编写上面的表单,我们可以使用非常类似于HTML的语法来编写它:

// Example 4 - JSX (compare with Example 3)
// https://jscomplete.com/repl?j=SJWy3otHW
const InputForm =<form target="_blank" action="https://google.com/search"><div>Enter input and click Search</div><input name="q" className="input" /><Button label="Search" /></form>;
// InputForm "still" uses the Button component, so we need that too.
// Either JSX or normal form would do
function Button (props) {// Returns a DOM element here. For example:return <button type="submit">{props.label}</button>;
}
// Then we can use InputForm directly with .render
ReactDOM.render(InputForm, mountNode);

Note a few things about the above:

请注意上述几点:

  • It’s not HTML. For example, we’re still doing className instead of class.

    不是HTML。 例如,我们仍在使用className代替class

  • We’re still considering what looks like HTML above as JavaScript. See how I added a semicolon at the end.我们仍在考虑上面看起来像HTMLJavaScript。 看看我如何在末尾添加分号。

What we wrote above (Example 4) is JSX. Yet, what we took to the browser is the compiled version of it (Example 3). To make that happen, we need to use a pre-processor to convert the JSX version into the React.createElement version.

上面我们写的(示例4)是JSX。 但是,我们带给浏览器的是它的编译版本(示例3)。 为此,我们需要使用预处理器将JSX版本转换为React.createElement版本。

That is JSX. It’s a compromise that allows us to write our React components in a syntax similar to HTML, which is a pretty good deal.

那就是JSX。 这是一个折衷方案,使我们能够以类似于HTML的语法编写React组件,这是非常不错的。

The word “Flux” in the header above was chosen to rhyme, but it’s also the name of a very popular application architecture popularized by Facebook. The most famous implementation of which is Redux. Flux fits the React reactive pattern perfectly.

上面标题中的“ Flux”一词被选为押韵,但这也是Facebook流行的非常流行的应用程序体系结构的名称。 其中最著名的实现是Redux。 助焊剂非常适合ReactReact模式。

JSX, by the way, can be used on its own. It’s not a React-only thing.

顺便说一下,JSX可以单独使用。 这不是只做React的事情。

基本原理3:您可以在JSX中的任何位置使用JavaScript表达式 (Fundamental 3: You can use JavaScript expressions anywhere in JSX)

Inside a JSX section, you can use any JavaScript expression within a pair of curly braces.

在JSX部分中,您可以在一对花括号内使用任何JavaScript表达式。

// To use it:ReactDOM.render(<RandomValue />, mountNode);// Example 5 -  Using JavaScript expressions in JSX
// https://jscomplete.com/repl?j=SkNN3oYSW
const RandomValue = () => <div>{ Math.floor(Math.random() * 100) }</div>;
// To use it:
ReactDOM.render(<RandomValue />, mountNode);

Any JavaScript expression can go inside those curly braces. This is equivalent to the ${} interpolation syntax in JavaScript template literals.

任何JavaScript表达式都可以放在这些花括号内。 这等效于JavaScript 模板文字中的${}插值语法。

This is the only constraint inside JSX: only expressions. So, for example, you can’t use a regular if statement, but a ternary expression is ok.

这是JSX内部的唯一约束:仅表达式。 因此,例如,您不能使用正则if语句,但可以使用三元表达式。

JavaScript variables are also expressions, so when the component receives a list of props (the RandomValue component didn’t, props are optional), you can use these props inside curly braces. We did this in the Button component above (Example 1).

JavaScript变量也是表达式,因此当组件接收到一系列道具时( RandomValue组件没有, props是可选的),您可以在花括号内使用这些道具。 我们在上面的Button组件中进行了此操作(示例1)。

JavaScript objects are also expressions. Sometimes we use a JavaScript object inside curly braces, which makes it look like double curly braces, but it’s really just an object inside curly braces. One use case of that is to pass a CSS style object to the special style attribute in React:

JavaScript对象也是表达式。 有时我们在花括号内使用JavaScript对象,这使其看起来像双花括号,但实际上只是花括号内的对象。 一个用例是将CSS样式对象传递给React中的特殊style属性:

// Example 6 - An object passed to the special React style prop
// https://jscomplete.com/repl?j=S1Kw2sFHb
const ErrorDisplay = ({message}) =><div style={ { color: 'red', backgroundColor: 'yellow' } }>{message}</div>;
// Use it:
ReactDOM.render(<ErrorDisplay message="These aren't the droids you're looking for" />,mountNode
);

Note how I destructured only the message out of the props argument. Also note how the style attribute above is a special one (again, it’s not HTML, it’s closer to the DOM API). We use an object as the value of the style attribute. That object defines the styles as if we’re doing so with JavaScript (because we are).

请注意我是如何从props参数中解构出消息的。 还要注意上面的style属性是如何特殊的(同样,它不是HTML,它更接近DOM API)。 我们使用一个对象作为style属性的值。 该对象定义样式,就像我们使用JavaScript一样(因为是)。

You can even use a React element inside JSX, because that too is an expression. Remember, a React element is essentially a function call:

您甚至可以在JSX中使用React元素,因为那也是一个表达式。 记住,React元素本质上是一个函数调用:

// Example 7 - Using a React element within {}
// https://jscomplete.com/repl?j=SkTLpjYr-
const MaybeError = ({errorMessage}) =><div>{errorMessage && <ErrorDisplay message={errorMessage} />}</div>;// The MaybeError component uses the ErrorDisplay component:
const ErrorDisplay = ({message}) =><div style={ { color: 'red', backgroundColor: 'yellow' } }>{message}</div>;
// Now we can use the MaybeError component:
ReactDOM.render(<MaybeErrorerrorMessage={Math.random() > 0.5 ? 'Not good' : ''}/>,mountNode
);

The MaybeError component above would only display the ErrorDisplay component if there is an errorMessage string passed to it and an empty div. React considers {true}, {false}, {undefined}, and {null} to be valid element children, which do not render anything.

如果传递了errorMessage字符串和一个空div ,则上面的MaybeError组件将仅显示ErrorDisplay组件。 React认为{true}{false}{undefined}{null}是有效的元素子元素,它们不会呈现任何内容。

You can also use all of JavaScript functional methods on collections (map, reduce, filter, concat, and so on) inside JSX. Again, because they return expressions:

您还可以在JSX内的集合( mapreducefilterconcat等)上使用所有JavaScript功能方法。 同样,因为它们返回表达式:

// Example 8 - Using an array map inside {}
// https://jscomplete.com/repl?j=SJ29aiYH-
const Doubler = ({value=[1, 2, 3]}) =><div>{value.map(e => e * 2)}</div>;
// Use it
ReactDOM.render(<Doubler />, mountNode);

Note how I gave the value prop a default value above, because it’s all just Javascript. Note also that I outputted an array expression inside the div. React is okay with that; It will place every doubled value in a text node.

请注意,我是如何给value prop设置上面的默认值的,因为它们全都是Javascript。 还要注意,我在div输出了一个数组表达式。 React对此还可以; 它将每个双精度值放置在文本节点中。

基础知识4:您可以使用JavaScript类编写React组件 (Fundamental 4: You can write React components with JavaScript classes)

Simple function components are great for simple needs, but sometimes we need more. React supports creating components through the JavaScript class syntax as well. Here’s the Button component (in Example 1) written with the class syntax:

简单的功能组件非常适合简单的需求,但有时我们需要更多。 React也支持通过JavaScript类语法创建组件。 这是用类语法编写的Button组件(在示例1中):

// Example 9 - Creating components using JavaScript classes
// https://jscomplete.com/repl?j=ryjk0iKHb
class Button extends React.Component {render() {return <button>{this.props.label}</button>;}
}
// Use it (same syntax)
ReactDOM.render(<Button label="Save" />, mountNode);

The class syntax is simple. Define a class that extends React.Component (another top-level React API thing that you need to learn). The class defines a single instance function render(), and that render function returns the virtual DOM element. Every time we use the Button class-based component above (for example, by doing <Button ... />), React will instantiate an object from this class-based component and use that object to render a DOM element in the DOM tree.

类语法很简单。 定义一个扩展React.Component的类(您需要学习的另一个顶级React API东西)。 该类定义单个实例函数render() ,并且该渲染函数返回虚拟DOM元素。 每次我们使用上面的基于Button类的组件时(例如,通过执行<Button ... />),React将从该基于类的组件中实例化一个对象,并使用该对象在DOM树中呈现DOM元素。 。

This is the reason why we used this.props.label inside the JSX in the rendered output above. Because every element rendered through a class component gets a special instance property called props that holds all values passed to that element when it was created.

这就是为什么我们在上面呈现的输出中的JSX中使用this.props.label的原因。 因为通过类组件呈现的每个元素都会获得一个称为props的特殊实例属性,该属性保存创建时传递给该元素的所有值。

Since we have an instance associated with a single use of the component, we can customize that instance as we wish. We can, for example, customize it after it gets constructed by using the regular JavaScript constructor function:

由于我们有一个与组件的单一使用相关联的实例,因此我们可以根据需要自定义该实例。 例如,我们可以在使用常规JavaScript constructor函数构造后对其进行自定义:

// Example 10 -  Customizing a component instance
// https://jscomplete.com/repl?j=rko7RsKS-
class Button extends React.Component {constructor(props) {super(props);this.id = Date.now();}render() {return <button id={this.id}>{this.props.label}</button>;}
}
// Use it
ReactDOM.render(<Button label="Save" />, mountNode);

We can also define class functions and use them anywhere we wish, including inside the returned JSX output:

我们还可以定义类函数,并在希望的任何地方使用它们,包括在返回的JSX输出内部:

// Example 11 — Using class properties
// https://jscomplete.com/repl?j=H1YDCoFSb
class Button extends React.Component {clickCounter = 0;handleClick = () => {console.log(`Clicked: ${++this.clickCounter}`);};render() {return (<button id={this.id} onClick={this.handleClick}>{this.props.label}</button>);}
}
// Use it
ReactDOM.render(<Button label="Save" />, mountNode);

Note a few things about Example 11 above:

请注意上述示例11的一些注意事项:

  • The handleClick function is written using the new proposed class-field syntax in JavaScript. This is still at stage-2, but for many reasons it’s the best option to access the component mounted instance (thanks to arrow functions). But, you need to use a compiler like Babel configured to understand stage-2 (or the class-field syntax) to get the code above to work. The jsComplete REPL has that pre-configured.

    handleClick函数是使用JavaScript中新提议的类字段语法编写的。 这仍然处于阶段2,但是由于许多原因,这是访问组件安装的实例的最佳选择(由于使用了箭头功能)。 但是,您需要使用像Babel这样的编译器,将其配置为了解Stage-2(或类字段语法),才能使上面的代码正常工作。 jsComplete REPL已预先配置。

  • We’ve also defined the clickCounter instance variables using the same class-field syntax. This allows us to skip using a class constructor call altogether.

    我们还使用相同的类字段语法定义了clickCounter实例变量。 这使我们可以完全跳过使用类构造函数的调用。

  • When we specified the handleClick function as the value of the special onClick React attribute, we did not call it. We passed in the reference to the handleClick function. Calling the function on that level is one of the most common mistakes when working with React.

    当我们将handleClick函数指定为特殊onClick React属性的值时,我们没有调用它。 我们将引用传递给handleClick函数。 在使用React时,在该级别上调用函数是最常见的错误之一。

// Wrong:
onClick={this.handleClick()}
// Right:
onClick={this.handleClick}

基础5:React中的事件:两个重要区别 (Fundamental 5: Events in React: Two Important Differences)

When handling events inside React elements, there are two very important differences from the way we do so with the DOM API:

在React元素内部处理事件时,与我们使用DOM API的方式有两个非常重要的区别:

  • All React elements attributes (events included) are named using camelCase, rather than lowercase. It’s onClick, not onclick.

    所有React元素属性(包括事件)都使用camelCase命名,而不是小写 。 它是onClick ,而不是onclick

  • We pass an actual JavaScript function reference as the event handler, rather than a string. It’s onClick={handleClick}, not onClick="handleClick".

    我们传递实际JavaScript函数引用作为事件处理程序,而不是字符串。 它是onClick={ handleClick } ,而不是onClick=" handleClick"

React wraps the DOM event object with an object of its own to optimize the performance of events handling. But inside an event handler, we can still access all methods available on the DOM event object. React passes that wrapped event object to every handle call. For example, to prevent a form from the default submission action, you can do:

React用自己的对象包装DOM事件对象,以优化事件处理的性能。 但是在事件处理程序内部,我们仍然可以访问DOM事件对象上可用的所有方法。 React将包装的事件对象传递给每个句柄调用。 例如,要阻止表单执行默认的提交操作,可以执行以下操作:

// Example 12 - Working with wrapped events
// https://jscomplete.com/repl?j=HkIhRoKBb
class Form extends React.Component {handleSubmit = (event) => {event.preventDefault();console.log('Form submitted');};render() {return (<form onSubmit={this.handleSubmit}><button type="submit">Submit</button></form>);}
}
// Use it
ReactDOM.render(<Form />, mountNode);

基本原理6:每个React组件都有一个故事 (Fundamental 6: Every React component has a story)

The following applies to the class component only (those that extend React.Component). Function components have a slightly different story.

以下内容仅适用于类组件(那些扩展了React.Component )。 功能组件的故事略有不同。

  1. First, we define a template for React to create elements from the component.首先,我们为React定义一个模板,以从组件创建元素。
  2. Then, we instruct React to use it somewhere. For example, inside a render call of another component, or with ReactDOM.render.

    然后,我们指示React在某处使用它。 例如,在另一个组件的render调用中,或在ReactDOM.render

  3. Then, React instantiates an element and gives it a set of props that we can access with this.props. Those props are exactly what we passed in step 2 above.

    然后,React实例化一个元素,并为其提供一组道具 ,我们可以使用this.props访问。 这些道具正是我们在上面的步骤2中通过的。

  4. Since it’s all JavaScript, the constructor method will be called (if defined). This is the first of what we call: component lifecycle methods.

    由于全部使用JavaScript,因此将调用constructor方法(如果已定义)。 这是我们所谓的第一个: 组件生命周期方法

  5. React then computes the output of the render method (the virtual DOM node).然后,React计算render方法(虚拟DOM节点)的输出。
  6. Since this is the first time React is rendering the element, React will communicate with the browser (on our behalf, using the DOM API) to display the element there. This process is commonly known as mounting.

    由于这是React首次渲染元素,因此React将与浏览器通信(代表我们,使用DOM API)以在其中显示元素。 此过程通常称为安装

  7. React then invokes another lifecycle method, called componentDidMount. We can use this method to, for example, do something on the DOM that we now know exists in the browser. Prior to this lifecycle method, the DOM we work with was all virtual.

    然后,React调用另一个生命周期方法,称为componentDidMount 。 例如,我们可以使用此方法在DOM上执行某些我们现在知道存在于浏览器中的操作。 在使用这种生命周期方法之前,我们使用的DOM都是虚拟的。

  8. Some components stories end here. Other components get unmounted from the browser DOM for various reasons. Right before the latter happens, React invokes another lifecycle method, componentWillUnmount.

    一些组件的故事到此结束。 由于各种原因,其他组件也会从浏览器DOM中卸载。 就在后者发生之前,React调用了另一个生命周期方法componentWillUnmount

  9. The state of any mounted element might change. The parent of that element might re-render. In either case, the mounted element might receive a different set of props. React magic happens here and we actually start needing React at this point! Prior to this point, we did not need React at all, honestly.

    任何已安装元素的状态都可能更改。 该元素的父元素可能会重新呈现。 在任何一种情况下,已安装的元素可能会接收到不同的道具集。 React魔术在这里发生,我们此时实际上开始需要 React! 在此之前,老实说,我们根本不需要React。

The story of this component continues, but before it does, we need to understand this state thing that I speak of.

此组件的故事还在继续,但它之前,我们需要了解这个国家的事情,我说的。

基本原理7:React组件可以具有私有状态 (Fundamental 7: React components can have a private state)

The following is also only applicable to class components. Did I mention that some people call presentational-only components dumb?

以下内容也仅适用于类组件。 我是否提到有些人称仅表示组件愚蠢

The state property is a special one in any React class component. React monitors every component state for changes. But for React to do so efficiently, we have to change the state field through another React API thing that we need to learn, this.setState:

state属性在任何React类组件中都是一个特殊的属性。 React监视每个组件状态的更改。 但是为了使React有效地做到这一点,我们必须通过需要学习的另一个React API事物this.setState来更改状态字段:

// Example 13 -  the setState API
// https://jscomplete.com/repl?j=H1fek2KH-
class CounterButton extends React.Component {state = {clickCounter: 0,currentTimestamp: new Date(),};handleClick = () => {this.setState((prevState) => {return { clickCounter: prevState.clickCounter + 1 };});};componentDidMount() {setInterval(() => {this.setState({ currentTimestamp: new Date() })}, 1000);}render() {return (<div><button onClick={this.handleClick}>Click</button><p>Clicked: {this.state.clickCounter}</p><p>Time: {this.state.currentTimestamp.toLocaleString()}</p></div>);}
}
// Use it
ReactDOM.render(<CounterButton />, mountNode);

This is the most important example to understand. It will basically complete your fundamental knowledge of the React way. After this example, there are a few other small things that you need to learn, but it’s mostly you and your JavaScript skills from that point.

这是最重要的例子。 它将基本完成您对React方法的基础知识。 在此示例之后,还需要学习其他一些小知识,但是从那时起,主要是您和您JavaScript技能。

Let’s walk through Example 13, starting with class fields. It has two of them. The special state field is initialized with an object that holds a clickCounter that starts with 0, and a currentTimestamp that starts with new Date().

让我们从类字段开始讲解示例13。 它有两个。 特殊state字段由一个对象初始化,该对象包含一个以0开头的clickCounter和一个以new Date()开头的currentTimestamp

The second class field is a handleClick function, which we passed to the onClick event for the button element inside the render method. The handleClick method modifies this component instance state using setState. Take notice of that.

第二个类字段是handleClick函数,我们将其传递给render方法内button元素的onClick事件。 handleClick方法使用setState修改此组件实例状态。 注意这一点。

The other place we’re modifying the state is inside an interval timer that we started inside the componentDidMount lifecycle method. It ticks every second and executes another call to this.setState.

我们要修改状态的另一个地方是在componentDidMount生命周期方法内启动的间隔计时器内。 它每秒滴答this.setState并执行对this.setState另一个调用。

In the render method, we used the two properties we have on the state with a normal read syntax. There is no special API for that.

在render方法中,我们使用正常读取语法在状态上使用了两个属性。 对此没有特殊的API。

Now, notice that we updated the state using two different ways:

现在,请注意,我们使用两种不同的方式来更新状态:

  1. By passing a function that returned an object. We did that inside the handleClick function.

    通过传递返回对象的函数。 我们在handleClick函数中进行了此操作。

  2. By passing a regular object. We did that inside the interval callback.通过传递常规对象。 我们是在时间间隔回调中完成的。

Both ways are acceptable, but the first one is preferred when you read and write to the state at the same time (which we do). Inside the interval callback, we’re only writing to the state and not reading it. When in doubt, always use the first function-as-argument syntax. It’s safer with race conditions because setState should always be treated as an asynchronous method.

两种方法都可以接受,但是当您同时读取和写入状态时(我们这样做),首选第一种方法。 在时间间隔回调中,我们仅写入状态,而不读取状态。 如有疑问,请始终使用第一个函数自变量语法。 在竞争条件下更安全,因为setState应该始终被视为异步方法。

How do we update the state? We return an object with the new value of what we want to update. Notice how in both calls to setState, we’re only passing one property from the state field and not both. This is completely okay because setState actually merges what you pass it (the returned value of the function argument) with the existing state. So, not specifying a property while calling setState means that we wish to not change that property (but not delete it).

我们如何更新状态? 我们返回一个具有我们要更新的新值的对象。 请注意,在两次调用setState ,我们仅从状态字段传递一个属性,而不是两者。 这完全可以,因为setState实际上您传递的内容(函数参数的返回值)与现有状态合并。 因此,在调用setState未指定属性意味着我们希望不更改该属性(但不要删除它)。

基础8:React会做出React (Fundamental 8: React will react)

React gets its name from the fact that it reacts to state changes (although not reactively, but on a schedule). There was a joke that React should have been named Schedule!

React之所以得名,是因为它对状态更改做出了React (尽管不是被动的,而是按计划进行的)。 开个玩笑说React应该被命名为Schedule

However, what we witness with the naked eye when the state of any component gets updated is that React reacts to that update and automatically reflects the update in the browser DOM (if needed).

但是,当任何组件的状态被更新时,我们用肉眼看到的是,React对更新进行React,并自动在浏览器DOM中反映该更新(如果需要)。

Think of the render function’s input as both:

将渲染函数的输入都视为:

  • The props that get passed by the parent父母通过的道具
  • The internal private state that can be updated anytime可以随时更新的内部私有状态

When the input of the render function changes, its output might change.

当渲染函数的输入更改时,其输出可能更改。

React keeps a record of the history of renders and when it sees that one render is different than the previous one, it’ll compute the difference between them and efficiently translate it into actual DOM operations that get executed in the DOM.

React记录了渲染的历史记录,当发现一个渲染与上一个渲染不同时,React将计算它们之间的差异,并将其有效地转换为在DOM中执行的实际DOM操作。

基础知识9:React是您的代理 (Fundamental 9: React is your agent)

You can think of React as the agent we hired to communicate with the browser. Take the current timestamp display above as an example. Instead of us manually going to the browser and invoking DOM API operations to find and update the p#timestamp element every second, we just changed a property on the state of the component and React did its job of communicating with the browser on our behalf. I believe this is the true reason why React is popular. We hate talking to Mr. Browser (and the so many dialects of the DOM language that it speaks) and React volunteered to do all the talking for us, for free.

您可以将React视为我们雇用的与浏览器进行通信的代理。 以上面的当前时间戳显示为例。 代替我们手动去浏览器并每秒调用DOM API操作来查找和更新p#timestamp元素,我们只是更改了组件状态的属性,而React代表我们与浏览器进行通信。 我相信这是React受欢迎的真正原因。 我们讨厌与Browser先生(以及它所讲的DOM语言的众多方言)交谈,而React自愿为我们免费进行所有交谈。

基础知识10:每个React组件都有一个故事(第2部分) (Fundamental 10: Every React component has a story (part 2))

Now that we know about the state of a component and how when that state changes some magic happens, let’s learn the last few concepts about that process.

既然我们已经知道了组件的状态以及该状态如何发生变化,那么就会发生一些不可思议的事情,让我们学习有关该过程的最后几个概念。

  1. A component might need to re-render when its state gets updated or when its parent decides to change the props that it passed to the component当组件的状态得到更新或其父对象决定更改传递给组件的道具时,可能需要重新渲染组件
  2. If the latter happens, React invokes another lifecycle method, componentWillReceiveProps.

    如果发生后者,React将调用另一个生命周期方法componentWillReceiveProps

  3. If either the state object or the passed-in props are changed, React has an important decision to do. Should the component be updated in the DOM? This is why it invokes another important lifecycle method here, shouldComponentUpdate. This method is an actual question, so if you need to customize or optimize the render process on your own, you have to answer that question by returning either true or false.

    如果更改了状态对象或传入的道具,React将做出重要决定。 是否应在DOM中更新组件? 这就是为什么它在这里调用另一个重要的生命周期方法shouldComponentUpdate 。 这个方法是一个实际的问题,所以如果你需要定制或自己进行优化渲染过程中,可以通过返回true false来回答这个问题。

  4. If there is no custom shouldComponentUpdate specified, React defaults to a very smart thing that’s actually good enough in most situations.

    如果没有指定自定义的shouldComponentUpdate ,React默认会是一个非常聪明的东西,实际上在大多数情况下已经足够了。

  5. First, React invokes another lifecycle method at this point, componentWillUpdate. React will then compute the new rendered output and compare it with the last rendered output.

    首先,React此时会调用另一个生命周期方法componentWillUpdate 。 然后,React将计算新的渲染输出并将其与最后渲染的输出进行比较。

  6. If the rendered output is exactly the same, React does nothing (no need to talk to Mr. Browser).如果渲染的输出完全相同,则React不执行任何操作(无需与Browser先生交谈)。
  7. If there is a difference, React takes that difference to the browser, as we’ve seen before.如果存在差异,React会将差异引入浏览器,如我们之前所见。
  8. In any case, since an update process happened anyway (even if the output was exactly the same), React invokes the final lifecycle method, componentDidUpdate.

    无论如何,由于无论如何都会发生更新过程(即使输出完全相同),因此React会调用最终的生命周期方法componentDidUpdate

Lifecycle methods are actually escape hatches. If you’re not doing anything special, you can create full applications without them. They’re very handy for analyzing what is going on in the application and for further optimizing the performance of React updates.

生命周期方法实际上是逃生舱口。 如果您没有做任何特别的事情,则可以在没有它们的情况下创建完整的应用程序。 对于分析应用程序中发生的事情以及进一步优化React更新的性能,它们非常方便。

That’s it. Believe it or not, with what you learned above (or parts of it, really), you can start creating some interesting React applications. If you’re hungry for more, check out my Learn React.js by Building Games book!

而已。 信不信由你,使用上面的知识(或部分知识),您可以开始创建一些有趣的React应用程序。 如果您渴望获得更多,请查看我的《 Building Games学习Learn.js》一书!

Thanks to the many readers who reviewed and improved this article, Łukasz Szewczak, Tim Broyles, Kyle Holden, Robert Axelse, Bruce Lane, Irvin Waldman, and Amie Wilt.

ŁukaszSzewczak,Tim Broyles,Kyle Holden,Robert Axelse,Bruce Lane,Irvin Waldman和Amie Wilt感谢许多阅读和改进本文的读者。

Learning React or Node? Checkout my books:

学习React还是Node? 结帐我的书:

  • Learn React.js by Building Games

    通过构建游戏学习React.js

  • Node.js Beyond the Basics

    超越基础的Node.js

翻译自: https://www.freecodecamp.org/news/all-the-fundamental-react-js-concepts-jammed-into-this-single-medium-article-c83f9b53eac2/

撰写本文的所有基本React.js概念相关推荐

  1. MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录...

    注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...

  2. react 使用 svg_使用SVG和React.js构建日历热图

    react 使用 svg 跳舞语法 (Dancing Syntax) 介绍 (Introduction) In 2016, I had put my academic plans on hold af ...

  3. React.js 小书 Lesson27 - 实战分析:评论功能(六)

    React.js 小书 Lesson27 - 实战分析:评论功能(六) 本文作者:胡子大哈 本文原文:http://huziketang.com/books/react/lesson27 转载请注明出 ...

  4. React.js核心原理实现:首次渲染机制

    2019独角兽企业重金招聘Python工程师标准>>> 一.前言 react.js和vue.js无疑是当下最火的js框架了,它们为组件式的开发传统前端页面.SPA页面.前后端分离等带 ...

  5. React.js 2016 最佳实践 徬梓阅读 1584收藏 71

    为什么80%的码农都做不了架构师?>>>    译者按:近几个月React相关话题依旧火热,相信越来越多的开发者在尝试这样一项技术,我们团队也在PC和移动端不断总结经验.2016来了 ...

  6. 编写react组件_如何编写第一个React.js组件

    编写react组件 React的函数和类组件,道具,状态和事件处理程序 (React's function and class components, props, state, and event ...

  7. React.js 小书 Lesson1-2 - 前端组件化(一):从一个简单的例子讲起

    React.js 小书 Lesson1-2 - 前端组件化(一):从一个简单的例子讲起 本文作者:胡子大哈 本文原文:http://huziketang.com/books/react/lesson2 ...

  8. 必须收藏!这13个优秀React JS框架,没用过就很离谱!

    如果你正在使用React.js或React Native创建用户界面,可以试一试本文推荐的这些框架.   React.js和React Native是流行的用户界面(UI)开发平台,且都是开源技术.在 ...

  9. react.js开发_2020 React.js开发人员路线图

    react.js开发 成为阅读JS开发人员的插图指南,其中包含相关课程的链接 React JS或简称React是用于开发Web应用程序的前端或GUI的领先JavaScript库之一. 在Faceboo ...

最新文章

  1. 8软件遇到的问题及解决方法_问题解决8步法
  2. IE9下iframe显示异常的处理方法
  3. 集成ShareSDK里报错NSConcreteMutableData wbsdk_base64EncodedString]
  4. 数据分析师常用的十种数据分析思路,你都知道吗?
  5. 深入redis内部之redis启动过程之一
  6. 【模型解读】GoogLeNet中的inception结构,你看懂了吗
  7. 灵魂画手:漫画图解 SSH
  8. 程序逻辑上多一些提示
  9. mysql 迁移 nosql_从关系型Mysql到Nosql HBase的迁移实践
  10. 使用rust编译linux,在 Ubuntu 上为 CentOS 编译 Rust 程序,
  11. 深圳先进院研究生计算机专业,2020年中科院深圳先进技术研究院全日制硕士研究生统考专业说明...
  12. dubbo服务RpcException异常:Tried 3 times of the providers 或com.alibaba.dubbo.remoting.TimeoutException
  13. 通俗易懂的MonteCarlo积分方法(六)
  14. 14个开源Ajax框架
  15. Oracle财务管理系统
  16. 【优化】1389- 万字长文:分享前端性能优化知识体系
  17. 手把手教大家在mac上用VMWare虚拟机装Ubuntu
  18. java.lang.RuntimeException:Unable to start activity ComponentInfo{com.meizu.beautify/com.my.viewc.Ma
  19. MySQL5.7安装教程(workbench安装教程会在之后出)(32位和64位均可)
  20. 《小狗钱钱》--chapter3.4.5--挖掘需求、排除干扰

热门文章

  1. linux 磁盘管理3板斧,Linux磁盘管理三板斧的使用心得
  2. 微信小程序之视图容器(swiper)组件创建轮播图
  3. MapXtreme2004 vs2005的官方回答
  4. 浅谈传统企业网络运营那些事儿
  5. 软件安装(JDK+MySQL+TOMCAT)
  6. 两个多项式相乘求解系数数组算法
  7. mysql benchmark基准测试
  8. 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 Jtop
  9. FFmpeg 是如何实现多态的?
  10. 温故而知新:柯里化 与 bind() 的认知