React 笔记—核心概念
本文基于官方 v18.1.0 文档。
Introducing JSX
React embraces the fact that rendering logic is inherently coupled with other UI logic:
how events are handled, how the state changes over time, and how the data is prepared for display.
Instead of artificially separating technologies by putting markup and logic in separate files,
React separates concerns with loosely coupled units called “components” that contain both.
这是当初 React 最吸引我的地方,不执著于将 UI 和逻辑分开。MVC 大行其道几十年后,Android 跟 iOS 也都在尝试返濮了。
在我实际工作经验中,进行视图子类化定制的出发点往往就是为了将 UI 和其逻辑写在一起。这个需求越靠近业务层就越强烈。
We split JSX over multiple lines for readability. While it isn’t required, when doing this,
we also recommend wrapping it in parentheses to avoid the pitfalls of automatic semicolon insertion.
Specifying Attributes with JSX
Since JSX is closer to JavaScript than to HTML, React DOM uses camelCase property naming convention instead of HTML attribute names.
For example, class becomes className in JSX, and tabindex becomes tabIndex.
JSX Prevents Injection Attacks
Everything is converted to a string before being rendered. This helps prevent XSS (cross-site-scripting) attacks.
Rendering Elements
Elements are the smallest building blocks of React apps.
Unlike browser DOM elements, React elements are plain objects, and are cheap to create.
React Only Updates What’s Necessary
React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring the DOM to the desired state.
Even though we create an element describing the whole UI tree on every tick, only the text node whose contents have changed gets updated by React DOM.
Components and Props
Always start component names with a capital letter.
React treats components starting with lowercase letters as DOM tags.
functions are called “pure” because they do not attempt to change their inputs, and always return the same result for the same inputs.
All React components must act like pure functions with respect to their props.
act like, 说的是组件看起来像纯函数——从 props 角度上讲,而不是真正意义上的纯函数。只是强调 props 的不可变性。
State and Lifecycle
Adding Lifecycle Methods to a Class
The componentDidMount()
method runs after the component output has been rendered to the DOM.
State Updates May Be Asynchronous
Because this.props
and this.state
may be updated asynchronously, you should not rely on their values for calculating the next state.
1 | // Correct |
Handling Events
you cannot return false
to prevent default behavior in React. You must call preventDefault
explicitly.
e
is a synthetic event.
In JavaScript, class methods are not bound by default. Understanding JavaScript Bind ()
If calling bind annoys you, there are two ways you can get around this.
- public class fields syntax
1 | class LoggingButton extends React.Component { |
- arrow function
1 | class LoggingButton extends React.Component { |
The problem with this syntax is that a different callback is created each time the LoggingButton
renders.
Conditional Rendering
Preventing Component from Rendering
In rare cases you might want a component to hide itself even though it was rendered by another component.
To do this return null
instead of its render output.
Returning null
from a component’s render
method does not affect the firing of the component’s lifecycle methods.
For instance componentDidUpdate
will still be called.
Lists and Keys
We don’t recommend using indexes for keys if the order of items may change.
This can negatively impact performance and may cause issues with component state.
If you choose not to assign an explicit key to list items then React will default to using indexes as keys.
Forms
In HTML, form elements such as <input>
, <textarea>
, and <select>
typically maintain their own state and update it based on user input.
In React, mutable state is typically kept in the state property of components, and only updated with setState()
.
We can combine the two by making the React state be the “single source of truth”.
Then the React component that renders a form also controls what happens in that form on subsequent user input.
An input form element whose value is controlled by React in this way is called a “controlled component”.
受控组件。简单说就是表单类 HTML 元素的 value 显示被 React 组件接管、控制了。
In HTML, a <textarea>
element defines its text by its children:
1 | <textarea> |
In React, a <textarea>
uses a value
attribute instead.
React, instead of using this selected
attribute, uses a value
attribute on the root select
tag.
You can pass an array into the value
attribute, allowing you to select multiple options in a select
tag.
Because its value is read-only, it is an uncontrolled component in React.
Note how we used the ES6 computed property name syntax to update the state key corresponding to the given input name:
1 | this.setState({ |
Computed property name: 计算属性名。把方括号内的表达式所表示的字符串值作为属性名。
Lifting State Up
In React, sharing state is accomplished by moving it up to the closest common ancestor of the components that need it. This is called “lifting state up”.
Composition vs Inheritance
Some components don’t know their children ahead of time. This is especially common for components like Sidebar
or Dialog
that represent generic “boxes”.
We recommend that such components use the special children
prop to pass children elements directly into their output.
While this is less common, sometimes you might need multiple “holes” in a component. In such cases you may come up with your own convention instead of using children
:
1 | function SplitPane(props) { |
Remember that components may accept arbitrary props, including primitive values, React elements, or functions.
Thinking in React
Use the same techniques for deciding if you should create a new function or object. One such technique is the single responsibility principle, that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents.