Website: ReactJS.doc - ZhaochengLi/Zhaocheng-s GitHub Wiki
-
Add a DOM container to the HTML; Open the HTML page you want to edit, and add an enpty
<div>
tag to mark the spot where you want to display something with React. Setting up an uniqueid
for the<div>
will allow us to find it from the JS code later and display a React component inside of it. Be aware the<div>
can be placed anywhere but inside the<body>
tag. You can have as many independent DOM containers on one page as you need. They are usually empty, React will replace any existing content inside DOM containers.<div id="like_botton_container"></div>
-
Add the script tags; Add three
<script>
tags to the HTML page right before the closing</body>
tag,// first two tags load React. <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/react-dom.development.js" crossorigin></script> // the last tag loads you component code <script src="like_button.js"></script>
-
Create a React Component; Create a file called like_button.js next to your HTML page, and after all the codes you wrote, add two lines to the bottom of it (as below), these two lines of code find the
<div>
we added before to our HTML in the first step, and then display out "Like" button React component inside of it.const domContainer=document.querySelector('#like_button_container'); ReactDOM.render(e(LikeButton), domContainer);
THAT'S IT!
(???)Notice: Reuse a component, it is a case that you wanto to display React components in multiple places on the HTML page.
We are going to use some popular React toolchains which help with tasks like:
- Scaling to many files and components;
- Using third-party libraries from npm;
- Detecting common mistakes early;
- Live-editing CSS and JS in development;
- Optimizing the output for production;
You might not need a toolchain. If you do not experience the problems desvribed above or do not feel feel comfortable using JavaScript yet, consider adding React as a plain <script>
tag on an HTML page, optionally with JSX. This is also the easiest way to integrate React into an existing website. You can always add a large toolchain if you find it helpful.
the React team primarily recommends these solutions:
- If you are learning React or creating a new single-page app, use
Create React App
; - If you are building a server-rendered website with Node.js, try
Next.js
; - If you are building a static content-oriented website, get
Gatsby
; - If you are building a component library or integrating with an existing codebase, try
More Flexible Toolchains
- Hello World
- Introducing JSX
- Rendering Elements
- Components and Props
- State and Lifecycle
- Handling Events
- Conditional Rendering
- Lists and Keys
- Forms
- Lifting State Up
- Composition vs Inheritance
- Thinking in React
This is the smallest React example,
ReactDOM.render(
<h1>Hello World</h1>,
document.getElementById("root")
);
- Why JSX?
- Embedding Expressions in JSX
- JSX is an expression too
- Specifying Attribtues with JSX
- Specifying Children with JSX
- JSX Prevents Injection Attacks
- JSX Represents Objects
Consider this variable declaration:
const element = <h1>Hello, world!</h1>;
This tag is neither a string nor HTML, it is called JSX, a syntax extension to JavaScript. And it is recommended using with React to describe what the UI should look like.
JSX produces React with "elements", we will explore rendering them to the DOM later. Now we are going to learn some basics about it.
React doesn't require using JSX, but most poeple find it helpful as a visual aid when working with UI inside the JavaScript code, it also allows React to show more useful error and warning messages.
-
we declare a variable named
name
and use it inside JSX by wrapping it in curly braces:const name = 'John Park'; const element = <h1>Hello, {name}</h1>; ReactDOM.render( element, document.getElementById('root') );
-
You can put any JavaScript expression inside the curly braces in JSX, such as
2+2
,user.firstName
, orformatName(user)
and so on. -
For example, we can embed the result of calling a JavaScript function,
formatName(user)
, into an<h1>
element.function formatName(user){ return user.firstName + ' ' + user.lastName; } const user={ firstName: 'Harper', lastName: 'Peres' }; const element = { <h1>Hello, {formatName(user)}!</h1> }; ReactDOM.render( element, document.getElementById('root') );
Notice that 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 pitfall of automatic semicolon insertion.
JSX expressions become regular JavaScript function calls and evaluate to JavaScript objects. This means that you can use JSX inside of if
statements and for
loops, assign it to variables, accept it as arguments, and return it from functions:
function getGreeting(user){
if(user){
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
You may use quotes to specify string literals as attributes:
const element = <div tabIndex="0"></div>;
You may also use curly braces to embed a JavaScript expression in an attribute:
const element = <img src={user.avatarUrl}></img>;
Do not put quotes around curly braces when embedding a JavaScript expression in an attribute. You should either use quotes(for string values) or curly braces(for expression), but not both in the same attribute.
Notice that since JSX is closer to JS than HTML, React DOM uses camelCase
property naming convention instead of HTML attributes names. For example, class
become className
in JSX, and tabindex
becomes tabIndex
.
If a tag is empty, you may close it immediately with />
, for example,
const element = <img src={user.avatarUrl} />;
JSX tags may also contain children,
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
It is safe to embed user input in JSX, as below. By default, React DOM escapes any values embedded in JSX before rendering them, thus it ensures you can never inject anything that's not explicitly written in your application. Everything is converted to a string bebore being rendered. This helps prevent XSS(cross-site-scripting)
attacks.
const title = response.potentiallyMaliciousInput;
// it is ok
const element = <h1>{title}</h1>;
The following two examples are identical:
const element (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement (
'h1',
{className: 'greeting'},
'Hello, world!'
);
React.createElement()
call performs a few checks to help you write bug-free code but essantially it creates an object like this,
// this structure is simplified
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
These objects are called React elements. You can think of them as descriptions of what you want to see on the screen. React read these objects and uses them to construct the DOM and keep it up to date.
An element describes what you want to see on the screen: (unlike browser DOM elements, React elements are plain objects, and are cheap to create. React DOM takes care of updating the DOM to match the React elements)
const element = <h1>Hello, world</h1>
Let's say there is a <div>
somewhere in your HTML file,
<div id="root"></div>
We will call this a "root" DOM node because everything inside it will be managed by React DOM. Applications built with just React usually have a single root DOM node, it you are integrating React into an existing app, you may have as many isolated root DOM nodes as you like.
To render a React element into a root DOM node, pass both to ReactDOM.render()
,
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));
// the "Hello, world" will be displayed on the page.
React elements are immutable, once you create an element, you cann't change its children or attributes. An element is like a single frame in a movie: it represents the Ul at a certain point in time.
With our knowledge so far, the only way to update the UI us to create a new element, and pass it to ReactDOM.render()
. Consider the ticking clock example,
function tick(){
const element = (
<div>
<h1>Hello, world</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);
You will notice that it calls ReactDOM.render()
ever second from a setInterval()
callback. But in practice, most React apps only call ReactDOM.render()
once. We will learn how such code gets encapsulated into stateful components.
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. Consider previous example, even though we create an element describing the whole UI tree on every tick, only the text node whose contents has changed gets updated by React DOM.
Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. This page provides an introduction to the idea of components. Conceptually, components are like JavaScript functions, they accept arbitrary inputs(called "props") and returns React elements describing what should appear on the screen.
The simplest way to define a component is to write a JavaScript function,
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
This function is a valid React component because it accepts a single "props" (which stands for properties) object argument with data and returns a React element. We call such components "Function components" because they are literally JS functions.
You can also use a class to define a component,
class Welcome extends React.component {
render(){
return <h1>Hello, {this.props.name}</h1>;
}
}
The above two components are equivalent from React's point of view. Classes have some additional features that we will discuss later.
Previously, we only encountered React elements that represent DOM tags,
const element = <div />;
However, elements can also represent user-defined components,
const element = <Welcome name="Sara" />;
When React sees an element representing a user-defined component, it passes JSX attributes to this component as a single object. We call this object "props". For example, the following code renders "Hello, Sara" on the page,
function Welcome(props){
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara " />;
ReactDOM.render(
element,
document.getElementById('root')
);
Let's recap what happens in this example,
- We call
ReactDOM.render()
with the<Welcome name="Sara" />
element. - React calls the
Welcome
component with{name: 'Sara'}
as the props. - Our
Welcome
component returns a<h1>Hello, Sara</h1>
element as the result. - React DOM efficiently updates the DOM to match
<h1>Hello, world</h1>
.
Notice: always start component names with a capital letter. React treats components starting with lowercase letters as DOM tags. For example, <div />
represents an HTML div tag, but <Welcome />
represents a component and requires Welcome
to be in scope.
Components can refer to other components in their outputs. This lets us use the same component abstraction for any level of detail. A button, a form, a dialog, a screen: in React apps, all those are commonly expressed as components.
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')
);
Typically, new React apps have a single App
component at the very top. However, if you integrate React into an existing app, you might start bottom-up with a small component like Button
and gradually work your way to the top of the view hierarchy.
Don't be afraid to aplit components into smaller components. For example, consider the Comment
component,
function Comment(props){
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
It accepts author
(an object), text
(a string), and date
(a date) as props, and describes a comment on a social media website. This component can be tricky to change because of all the nesting, and it is also hard to reuse individual parts of it. Let's extract a few components from it
First, we extract Avatar
,
function Avatar(props){
return <img className="Avatar" src={props.user.avatarUrl} alt={props.user.name} />;
}
Then we can extract UserInfo
,
function UserInfo(props){
return (
<div className="UserInfo">
<Avatar user={props.user}>
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
Then Comment
will be simplified like below
function Comment(props){
return {
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
Having a palette od reusable components pays off in larger app. A good rule of thumb is that if a part of your UI is used several time (Button
, Panel
, Avatar
), or is complex enough on its own (App
, FeedStory
, Comment
), it is a good condidate to be a reusable component.
Whether you declare a component as a function or a class, it must never modify its own props. Consider this sum
function,
function sum(a,b){
return a + b;
}
Such functions are called "pure" because they do not attempt to change their inputs, and always return the same result for the same inputs.
In contrast, this function is impure because it changes its own input:
function withdraw(account, amount){
account.total -= amount;
}
React is pretty flexible but it has a single strict rule: all React components must act like pure functions with respect to their props.
Of course, application UIs are dynamic and change over time. We will introduce a new concept of "state". State allows React components to change their output over time in response to user actions, network responses, and anything else, without violating this rule.
Consider the ticking clock example. In rendering elements, we have only learned one way to update the UI. We call ReactDOM.render()
to change the rendered output,
function tick(){
const element = (
<div>
<h1>Hello, world</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);
In this section, we will learn how to make the Clock
component truly reusable and encapsulated. It will set up its own timer and update itself every second.
We start by encapsulating how Clock
works, in order to make Clock
sets up a timer and updates the UI every second, we need to add 'state' to the Clock
component. State is similar to props, but it is private and fully controlled by the component.
funcion Clock(props){
return (
<div>
<h1>Hello, world</h1>
<h2>It is {props.date.toLocaleTimeString()}.
</div>
);
}
function tick(){
ReactDOM.render(
<Clock data={new Date()} />,
document.getElementById('root')
);
}
setInterval(tick, 1000);
We need to add some more to the code above.
-
Creates a class, with the same name, that extends
React.component
. -
Adds a single empty method to it called
render()
. -
Move the body of the function into the
render()
method. -
Replace
props
withthis.props
in therender()
body. -
Delete the remaining empty function declaration.
class Clock extends React.Component { render() { return ( <div> <h1>Hello, world</h1> <h2>It is {props.date.toLocaleTimeString()}. </div> ); } }
Now Clock
is a class rather than a function, render
method will be called each time an update happens, but as long as we render <Clock />
into the same DOM node, only a single instance of the Clock
class will be used. This lets us use additional features such as local state and lifecycle methods.
now we are going to move date
from props to state,
-
Replace
this.props.date
withthis.state.date
in therender()
method. -
Add a class constructor that assigns the initial
this.state
. Note how we passprops
to the base constructor, class components should always call the base constructor withprops
. -
Remove the
date
prop from the<Clock />
element. Now it should look like this,class Clock extends React.Component { constructor(props){ super(props); this.state = {data: new Date()}; } render(){ return ( <div> <h1>Hello, world</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <Clock />, document.getElementById('root') );
Then we will make the Clock
set up its own timer and update itself every second.
We want to set up a timer whenever the Clock
is rendered to the DOM for the first time. This is called 'mounting' in React.
We also want to clear the timer whenever the DOM produced by the Clock
is removed. This is called unmounting in React. We can declare special methods on the component class to run some code when a component mounts and unmounts. And these methods are called "lifecycle methods".
class Clock extends React.Component {
constructor(props){
super(props);
this.state = {data: new Date()};
}
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>
);
}
}
The componentDidMount()
method runs after the component output has been rendered to the DOM. This is a good place to set up a timer.
- When
<Clock /> is passed to ReactDOM.render()
, React calls the constructor of theClock
component. SinceClock
needs to display the current time, it initializesthis.state
with an object including the current time. We will later update this state. - React then calls the
Clock
component'srender()
method. This is how React learns what should be displayed on the screen. React then updates the DOM to match theClock
's render output. - When the
Clock
output is inserted in the DOM, React calls thecomponentDidMount()
lifecycle method. Inside it, theClock
component asks the browser to set up a timer to call the component'stick()
method once a second. - Every second the browser calls the
tick()
method. Inside it, theClock
component schedules a UI update by callingsetState()
with an object containing the current time. Thanks to thesetState()
call, React knows the state has changed, and calls therender()
method again to learn what should be on the screen. This time,this.state.data
in therender()
method will be different, and so the render output will include the updated time. React updates the DOM accordingly. - If the
Clock
component is ever removed from the DOM, React calls thecomponentWillUnmount()
lifecycle method so the timer is stopped.
There are three thing you should know about setState()
.
For example, this will not re-render a component,
// wrong
this.state.comment = "Hello";
Instead, use setState()
,
// correct
this.setState({comment: "Hello"});
The only place where you can assign this.state
is the constructor.
React may batch multiple setState()
calls into a single update for performance. Because this.props
and this.state
may be updated asynchronously, you should not rely on their values for calculating the next state.
For example, this code may fail to update the counter:
// fail
this.setState([
counter: this.state.counter + this.props.increment,
]);
to fix it, use a second form of setState()
that accepts a function rather than an object. The function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument,
// correct
this.setState(function(state, props){
return {
counter: state.counter + props.increment
};
});
When you call setState()
, React merges the object you provide into the current state. For example, you state may contain several independent variables,
constructor(props){
super(props);
this.state = {
posts: [],
comments: []
};
}
Then you can update them independently with separate setState()
calls,
componentDidMount(){
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
The merging is shallow, so this.setState({comments})
leaves this.state.posts
intact, but completely replaces this.state.comments
.
Neither parent nor child components can know if a certain component is stateful or stateless, and they shouldn't care whether it is defined as a function or a class. This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it.
A component may choose to pass its state down as props to its child components:
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
This also works for user-defined components:
<FormattedDate date={this.state.date} />
The FormattedDate
component would receive the date
in its props and wouldn't know whether it came from the Clock
's state, from the Clock
's props, or was typed by hand.
function FormattedDate(props){
return <h2>It is {props.date.toLocaleTimeString()}.</h2>;
}
This is commonly called a "top-down" or "undirectional" date flow. Any state is always owned by some specific component, and any data or UI derived from that state can only affect components "below" them in the tree.
If you imagine a component tree as a waterfall or props, each component's state is like an additional water source that joins it at an arbitrary point but also flows down.
To show that all components are truely isolated, we can create an App
component that renders three <Clock>
s,
function App() {
return (
<div>
<Clock />
<Clock />
<Clock />
</div>
);
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
Each Clock
sets up its own timer and updates independently. In React apps, whether a component is stateful or stateless is considered an implementation detail of the component that may change over time. You can use stateless components inside stateful components, and vice versa.
Handling events with React elements is very similar to handling events on DOM elements. There are some synthetic differences:
- React events are named using
camelCase
, rather than lowercase; - With JSX you pass a function as the event handler, rather than a string.
for example in HTML
<button onclick="activateLasers()">
Activate Lasers
</button>
while in React,
<button onClick={activateLasers}>
Activate Lasers
</button>
Another difference is that you cannot return false
to prevent dafault bahavior in React. You must call preventDefault
explicitly. For example, in HTML, to prevent the default link behavior of opening a new page, you can write,
<a href="#" onclick="console.log('The link was clicked'); return false">
Click me
</a>
In React, this could instead be,
function ActionLink(){
function handleClick(e){
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
Here, e
is a synthetic event. React defines these synthetic events sccording to the W3C spec, so you do not need to worry about cross-browser compatibility.
When using React you should generally not need to call addEventListener
to add listeners to a DOM element after it is created. Instead, just provide a listener when the element is initially rendered.
When you define a component using an class, a common pattern is for an event handler to be a method on the class. For example, this Toggle
component renders a button that lets the user toggle between ON
and OFF
state:
class Toggle extends React.Component {
constructor(props){
super(props);
this.state = {isToggleOn: true};
// this binding is necassary to make 'this' work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
this.setState(state ==> ({
isToggleOn: !state.isToggleOn
}));
}
render(){
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON':'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
You have to be careful about the meaning of this`` in JSX callbacks. In JavaScript, class methods are not *bound* by default. If you forget to bind
this.handleClickand pass it to
onClick,
thiswill be
undefined` when the function is actually called.
Insider a loop it is common to want to pass an extra parameter to an event handler. For example, if id
is the row ID
, either of the following would work:
<button onClick={(e) ==> this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
In React, you can create distinct components that encapsulate behavior you need. Then you can render only some of then, depending on the state of your application.
- Element Variables
- Inline If with Logical
&&
operator - Inline If-Else with Conditional Operator
- Preventing Component from Rendering
Consider the two components:
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props){
return <h1>Please sign up.</h1>;
}
We'll create a Greeting
component that displays either of these components depending on whether a user is logged in:
function Greeting(props){
const isLoggedIn = props.isLoggedIn;
if(isLoggedIn){
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// try changing to isLoggedIn={true};
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
You can use variables to store elements. This can help you conditionally render a part of the component while the rest of the output doesn't change.
Consider these two new components Logout
and Login
buttons:
function LoginButton(props){
return(
<button onClick={props.onClick}>
Login
</button>
);
}
function LogoutButton(props){
return (
<button onClick={props.onClick}>
Logout
</button>
);
}
We will create a stateful components called LoginControl
. It will render either or <LogoutButton />
depending on its current state.
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;
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')
);
You may embed any expressions in JSX by wrapping them in curly braces. This includes the JavaScript logical &&
operator. It can be handy for conditionally including an element:
function Mailbox(props){
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello</h1>
{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')
);
It works because in JavaScript, true && expression
always evaluates to expression
, and false && expression
always evaluates to false. Therefore, if the condition is true
, the element right after &&
will appear in the output.If it is false
, React wil and skip it..