1. Why does the React DOM use camelCase to define property names?
Because JSX is syntactically closer to JavaScript than HTML, the React DOM uses camelCase (small camel name) to define attribute names rather than the naming convention for HTML attribute names.
For example, the class in JSX becomes className and tabIndex becomes TabIndex.
JSX prevents injection attacks
You can safely insert user input into JSX:
const title = response.potentiallyMaliciousInput;
// It is safe to use directly:
const element = <h1>{title}</h1>;
Copy the code
The React DOM escapes by default before rendering all input. It ensures that you never inject content into your application that you didn’t explicitly write. All content is converted to a string before rendering. This effectively prevents XSS (cross-site scripting) attacks.
React elements and components
Unlike the browser DOM element, the React element is a generic object created with minimal overhead. The React DOM takes care of updating the DOM to be consistent with the React element.
The element is the smallest brick that makes up the React application. The element describes what you want to see on the screen.
const element = <h1>Hello, world</h1>;
Copy the code
Components are made up of elements.
4. The Root DOM node is managed by the React DOM
Let’s say you have a
<div id="root"></div>
Copy the code
We call this the “root” DOM node, because everything inside that node will be managed by the React DOM. To render a React element into the root DOM node, simply pass them together to reactdom.render ().
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
Copy the code
React elements are immutable objects
React elements are immutable objects. Once created, you can’t change its child elements or attributes. An element is like a single frame of a movie: it represents the UI at a particular moment.
Based on what we already know, the only way to update the UI is to create a brand new element and pass it to reactdom.render ().
In practice, most React applications only call reactdom.render () once.
React only updates what it needs to update
The React DOM compares elements and their children to their previous states and only makes necessary updates to bring the DOM to the expected state.
Although every second we create a new element that describes the entire UI tree, the React DOM only updates what’s actually changed.
7, components,
Note: Component names must begin with a capital letter.
React will treat components that begin with a lowercase letter as native DOM tags. For example,
represents an HTML div tag, while
represents a component and needs to use Welcome in scope. You can learn more about the reasons for this specification in in-depth JSX.
Function components and class components
Function component: This function is a valid React component because it takes a unique “props” (for properties) object with data and returns a React element. This type of component is called a “function component” because it is essentially a JavaScript function.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
Copy the code
ES6 class components
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>; }}Copy the code
Native DOM tag components and user-defined components
Native DOM tag components
const element = <div />;
Copy the code
User-defined components:
const element = <Welcome name="Sara" />;
Copy the code
When the React element is a user-defined component, it converts attributes and children received by JSX into a single object passed to the component, which is called “props.”
Compose components versus extract components
Components can reference other components in their output, and in general, the top component of every new React application is an App component.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
ReactDOM.render(
<App />.document.getElementById('root'));Copy the code
Extract components and break them up into smaller components. Extracting components may seem like a lot of work at first, but in large applications, building reusable component libraries is well worth it. As a rule of thumb, if part of the UI is used multiple times (Button, Panel, Avatar), or if the component itself is complex enough (App, FeedStory, Comment), then it is a good candidate for extracting individual components.
8. Read-only of Props
A component must never modify its props, either using a function declaration or through a class declaration. Such a function is called a “pure function” because it does not attempt to change the input parameter, and the same input parameter returns the same result multiple times.
React is very flexible, but it also has a strict rule:
All React components must protect their props from being changed like pure functions.
9, the state
Without violating the rules of the props section, state allows the React component to dynamically change its output in response to user actions, network responses, or other changes.
State is similar to props, but State is private and fully controlled by the current component.
The Render method is called every time a component is updated, but as long as the component is rendered in the same DOM node, only one class instance of the component is created and used.
Change the function component to a class component step
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
function tick() {
ReactDOM.render(
<Clock date={new Date()} / >.document.getElementById('root')); }setInterval(tick, 1000);
Copy the code
- The following five steps convert the Clock function component into a class component:
- Create an ES6 class with the same name and inherit from
React.Component
. - Add an empty
render()
Methods. - Move the function body to
render()
In the method. - in
render()
Method.this.props
replaceprops
. - Delete the remaining empty function declarations.
- Create an ES6 class with the same name and inherit from
- Add a local state to the class component by moving date from props to state in three steps:
- the
render()
In the methodthis.props.date
replacethis.state.date
. - Add a class constructor, and in that function for
this.state
To initialize, pass props to the constructor of the parent class in the following waysuper
In the function. A Class component should always call the parent constructor with the props argument - Removes the date attribute from the element
- the
- Add lifecycle methods to a Class and declare special methods for a Class component that will be executed when the component is mounted or unmounted:
- When the Clock component is first rendered into the DOM, a timer is set for it. “To mount”
- The componentDidMount() method runs after the component has been rendered into the DOM, so it’s a good idea to set a timer here
- Also, the timer should be cleared when the Clock component is removed from the DOM. “Unmount”
- use
this.setState()
To update component state from time to time
- When the Clock component is first rendered into the DOM, a timer is set for it. “To mount”
Although this.props and this.state are set by React itself and have special meanings, you can add extra fields to the class that don’t participate in the data flow (such as timer ID)
It is important to free up resources when a component is destroyed.
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date(a)}; }componentDidMount() {
this.timerID = setInterval(
() = > this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()}); }render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />.document.getElementById('root'));Copy the code
What happens and the order in which these methods are called:
- when
<Clock />
Are passed toReactDOM.render()
React calls the Clock component’s constructor. Because Clock needs to display the current time, it uses one that contains the current timeObject to initialize this.state. We will update state later. - And then React will call itThe component’s
render()
Methods. This is how React determines what to display on the page. Then the ReactUpdate the DOMTo match the output rendered by Clock. - When the Clock output is inserted into the DOMReact will call it
ComponentDidMount()
Lifecycle methods. In this method, the Clock component asks the browser to set a timer to call the component’s every secondtick()
Methods. - The browser calls it every second
tick()
Methods. In this method, the Clock component is calledsetState()
To plan a UI update.Thanks to thesetState()
React will know that the state has changed, and will recall the Render () method to determine what to display on the pageThis time,render()
In the methodthis.state.date
This will render out the updated time. React also updates the DOM accordingly. - Once the Clock component is removed from the DOMReact will call it
componentWillUnmount()
Lifecycle method, so the timer stops.
There are three things you should know about setState() :
Do not modify State directly
For example, this code does not re-render the component:
// Wrong
this.state.comment = 'Hello';
Copy the code
Instead, use setState():
// Correct
this.setState({comment: 'Hello'});
Copy the code
The constructor is the only place you can assign a value to this.state
Updates to State can be asynchronous
React may combine multiple setState() calls into a single call for performance reasons.
Because this.props and this.state may update asynchronously, you should not rely on their values to update the next state.
For example, this code might fail to update counters:
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
Copy the code
To solve this problem, make setState() accept a function instead of an object. This function uses a state as the first parameter and props as the second parameter when the update was applied:
// Correct
this.setState((state, props) = > ({
counter: state.counter + props.increment
}));
Copy the code
The arrow function was used above, but the normal function works just as well:
// Correct
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
Copy the code
Updates to the State are merged into the current State and are shallow merged
When you call setState(), React merges the objects you provide into the current state. For example, your state contains several independent variables:
constructor(props) {
super(props);
this.state = {
posts: [].comments: []}; }Copy the code
You can then call setState() to update them individually:
componentDidMount() {
fetchPosts().then(response= > {
this.setState({
posts: response.posts
});
});
fetchComments().then(response= > {
this.setState({
comments: response.comments
});
});
}
Copy the code
The merge here is shallow, so this.setState({comments}) keeps this.state.posts intact, but replaces this.state.comments completely.
11. Why is state local or encapsulated?
Neither parent nor child components know whether a component is stateful or stateless, and they do not care whether it is a function component or a class component.
None of the components are accessible except those that have and have state set.
12. Data flows downward
A component can optionally pass its state as props to its child components as attributes, and the child components will receive the parameters as attributes in its props, but the component itself has no way of knowing that it is derived from the parent component’s state. Or props of the parent component, or entered manually.
This is often referred to as “top-down” or “one-way” data flow. Any state is always owned by a particular component, and any data or UI derived from that state can only affect components “below” them in the tree.
If you think of a tree of components as a waterfall of props, then the state of each component is like adding additional water to the waterfall at any point, but it can only flow down.
Component instances are truly independent
These three
function App() {
return (
<div>
<Clock />
<Clock />
<Clock />
</div>
);
}
ReactDOM.render(
<App />.document.getElementById('root'));Copy the code
React event handling differs from DOM event handling
The React element’s event handling is similar to the DOM element’s, but there are a few syntactic differences:
- React events are named in a camelCase rather than pure lowercase.
- To use JSX syntax you need to pass in a function as an event handler, not a string.
- Another difference in React is that you can’t prevent default behavior by returning false. You have to use it explicitly
preventDefault
。
Traditional HTML
<button onclick="activateLasers()">
Activate Lasers
</button>
<a href="#" onclick="console.log('The link was clicked.'); return false">
Click me
</a>
Copy the code
React is a little different
Function component
function ActionLink() {
function handleClick(e) { // e is a composite event
e.preventDefault();
console.log('The link was clicked.');
}
return (
<div>
<button onClick={activateLasers}>
Activate Lasers
</button>
<a href="#" onClick={handleClick}>
Click me
</a>
</div>
);
}
Copy the code
Class component (3 method bindingsthis
)
You have to be careful with this in the JSX callback. In JavaScript, class methods do not bind this by default. If you forget to bind this.handleClick and pass it in onClick, this will be undefined when you call this function.
This isn’t React specific behavior; This has to do with how JavaScript functions work.
In general, if you don’t add () to the end of a method, such as onClick={this.handleclick}, you should bind this to the method
1. Declare event handlers as methods in class
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary in order to use 'this' in callbacks
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state= > ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
// this. HandleClick calls must bind this in the constructor
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />.document.getElementById('root'));Copy the code
2. If you find using BIND too cumbersome, you can use the experimental version that is being usedpublic class fields
grammar
Create React App enables this syntax by default.
class LoggingButton extends React.Component {
// This syntax ensures that 'this' in' handleClick 'is bound.
// Note: this is * experimental * syntax.
handleClick = () = > {
console.log('this is:'.this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>); }}Copy the code
3. If you do not use the class fields syntax, you can use it in the callbackArrow function
The problem with this syntax is that different callback functions are created each time you render.
In most cases, this is fine, but if the callback function is passed as a prop to child components, they may do additional re-rendering.
We generally recommend binding or using the Class Fields syntax in the constructor to avoid such performance problems.
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:'.this);
}
render() {
// This syntax ensures that 'this' in' handleClick 'is bound.
return (
<button onClick={()= > this.handleClick()}>
Click me
</button>); }}Copy the code
15. How do I pass parameters to event handlers?
If id is the ID of the row you want to delete, you can pass arguments to the event handler in either of the following ways:
<button onClick={(e) = > this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)} >Delete Row</button>
Copy the code
The two approaches are equivalent and are implemented using the arrow Function and function.prototype.bind respectively.
In both cases, the React event object E is passed as the second argument.
If the arrow function is used, the event object must be passed explicitly, whereas if bind is used, the event object and more parameters are passed implicitly.
16. Three ways of conditional rendering
if-else
- And the operator.
&&
- Ternary operator
condition ? true : false
The element variables
Use variables to store elements. It helps you conditionally render one part of a component without changing the rest of the rendering.
1. if-else
A stateful component of LoginControl.
It will render
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button; // Element variables
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
ReactDOM.render(
<LoginControl />.document.getElementById('root'));Copy the code
2. The and operator&&
You can embed expressions in JSX by wrapping code in curly braces.
In JavaScript, true && expression always returns expression, and false && expression always returns false.
Therefore, if the condition is true, the element to the right of && will be rendered, if it is false, React will ignore and skip it.
Note that an expression that returns false causes the element after && to be skipped but returns a false expression. In the following example, the render method returns
.
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
const count = 0;
return (
<div>
<h1>Hello!</h1>
{ count && <h1>Messages: {count}</h1>} // Returns'<h1>Hello!</h1> 0 ...`
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread messages.
</h2>
}
</div>
);
}
const messages = ['React'.'Re: React'.'Re:Re: React'];
ReactDOM.render(
<Mailbox unreadMessages={messages} />.document.getElementById('root'));Copy the code
3. Ternary operatorscondition ? true : false
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
{isLoggedIn
? <LogoutButton onClick={this.handleLogoutClick} />
: <LoginButton onClick={this.handleLoginClick} />
}
</div>
);
}
Copy the code
Preventing component rendering
In rare cases, you may want to hide a component even if it has been rendered by another component. To do this, you can have the Render method return NULL directly without doing any rendering.
function WarningBanner(props) {
if(! props.warn) {return null; // The render method returns null without doing any rendering
}
return (
<div className="warning">
Warning!
</div>
);
}
class Page extends React.Component {
constructor(props) {
super(props);
this.state = {showWarning: true};
this.handleToggleClick = this.handleToggleClick.bind(this);
}
handleToggleClick() {
this.setState(state= > ({
showWarning: !state.showWarning
}));
}
render() {
return (
<div>
<WarningBanner warn={this.state.showWarning} />
<button onClick={this.handleToggleClick}>
{this.state.showWarning ? 'Hide' : 'Show'}
</button>
</div>
);
}
}
ReactDOM.render(
<Page />.document.getElementById('root'));Copy the code
17,Why does the list have to contain a specialkey
Attribute?
Warning a key should be provided for list items, which means that when you create an element, you must include a special key property.
Key helps React identify which elements have changed, such as being added or removed. So you should give each element in the array a definite identity.
The key will pass information to React, but not to your components. Could not read props. Key.
If you need the value of the key attribute in your component, pass it explicitly with another attribute name.
An element’s key should ideally be a unique string that the element has in the list. Typically, we use the ID in the data as the element’s key.
The key must only be unique between sibling nodes
A key used in an array element should be unique among its siblings. However, they need not be globally unique. When we generate two different arrays, we can use the same key.
Example:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) = >
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
Copy the code
Is equivalent to:
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
Copy the code
JSX allows you to embed any expression in curly braces, which can sometimes make your code cleaner, but sometimes this style can be abused. Just as in JavaScript, it’s entirely up to you when you need to extract a variable for readability. But keep in mind that if a map() has too many levels nested, that might be a good time to extract components.
18. Why not use index as key?
As a last resort, you can use the element index as the key when the element has no specified ID. If the order of list items may change, we do not recommend using an index as a key value, as this can lead to poor performance and possibly component state issues. Check out Robin Pokorny’s in-depth analysis of the negative effects of using indexes as keys. If you choose not to specify an explicit key, React will default to using the index as the key for list items.
19, lists,key
Position of property
The element’s key makes sense only if it is placed in the context of the nearest array.
For example, if you extract a ListItem component, you should keep the key on the
function ListItem(props) {
const value = props.value;
return (
/ / error! You don't need to specify key here:
<li key={value.toString()}>
{value}
</li>
);
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) = >
/ / error! The element's key should be specified here:
<ListItem value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1.2.3.4.5];
ReactDOM.render(
<NumberList numbers={numbers} />.document.getElementById('root'));Copy the code
A good rule of thumb is that elements in the map() method need a key attribute.
function ListItem(props) {
/ / right! There is no need to specify key:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) = >
/ / right! The key should be specified in the context of the array
<ListItem key={number.toString()} value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1.2.3.4.5];
ReactDOM.render(
<NumberList numbers={numbers} />.document.getElementById('root'));Copy the code
Build React applications in composite mode
React has a very powerful combination mode. We recommend using composition rather than inheritance to achieve code reuse between components. How to solve these problems by combining ideas.
1. Containment relationships — used when considering “generic containers”
Some components do not know the details of their child components in advance.
This is especially true in the Sidebar and Dialog components that represent general-purpose containers.
props.children
We recommend that these components use a special Children Prop to pass their child components into the render result:
function FancyBorder(props) {
return (
<div className={'FancyBorder FancyBorder-'+props.color} >
{props.children}
</div>
);
}
Copy the code
This allows other components to be nested through JSX, passing any component to them as a child component.
function WelcomeDialog() {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
Welcome
</h1>
<p className="Dialog-message">
Thank you for visiting our spacecraft!
</p>
</FancyBorder>
);
}
Copy the code
Everything in the
JSX tag is passed to the FancyBorder component as a children Prop. Because FancyBorder renders {props. Children} in a
props
The concept of “slots” in other libraries
In rare cases, you may need to reserve several “holes” in a component. In this case, instead of using children, we can make a convention ourselves: pass the required content to props and use the appropriate prop.
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
function App() {
return (
<SplitPane
left={
<Contacts />
}
right={
<Chat />} / >
);
}
Copy the code
2. Special instance relationship
Sometimes we think of components as special instances of other components, and we can customize and render a “general” component to get a “special instance” component.
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="Thank you for visiting our spacecraft!" />
);
}
Copy the code
Comprehensive example
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
{props.children}
</FancyBorder>
);
}
class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {login: ' '};
}
render() {
return (
<Dialog title="Mars Exploration Program"
message="How should we refer to you?">
<input value={this.state.login}
onChange={this.handleChange} />
<button onClick={this.handleSignUp}>
Sign Me Up!
</button>
</Dialog>
);
}
handleChange(e) {
this.setState({login: e.target.value});
}
handleSignUp() {
alert(`Welcome aboard, The ${this.state.login}! `); }}Copy the code
React Philosophy
One of the best parts of React is getting us thinking, how do you build an application
Hook associated
Hook is a new feature in React 16.8.
Pay attention to
React 16.8.0 was the first release to support hooks. When upgrading, be sure to update all packages, including the React DOM. React Native supports hooks starting with version 0.59.
1. Why Hook?
It lets you use state and other React features without having to write a class.