# Quick Start https://facebook.github.io/react/docs/hello-world.html ## Hello World ```html Hello World
``` ## JSX ``` const element =

Hello, world!

; ``` JSX is a syntax extension to JavaScript, it produces React "elements". ### Embedding Expressions in JSX ``` function formatName(user) { return user.firstName + ' ' + user.lastName; } const user = {firstName: 'Harper', lastName: 'Perez'}; const element = (

Hello, {formatName(user)}!

); ReactDOM.render(element, document.getElementById('root')); ``` You can embed any JavaScript expression in JSX by wrapping it in curly braces. We split JSX over multiple lines for readability, when doing this, we also recommend wrapping it in parentheses to avoid the pitfalls of automatic semicolon insertion. ### JSX is an Expression Too After compilation, JSX expressions become regular 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: ### Specifying Attributes with JSX You may use quotes to specify string literals as attributes, you may also use curly braces to embed a JavaScript expression in an attribute. ``` const element =
; const element = ; ``` > Since JSX is closer to JavaScript than 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 It is safe to embed user input in JSX. By default, React DOM escapes any values embedded in JSX before rendering them. 如何嵌入 HTML 代码,估计又得折腾下。 ### JSX Represents Objects Babel compiles JSX down to `React.createElement()` calls. React.createElement() performs a few checks to help you write bug-free code but essentially it creates an object. These objects are called "React elements". You can think of them as descriptions of what you want to see on the screen. React reads these objects and uses them to construct the DOM and keep it up to date. ``` const element = (

Hello, world!

); // 等效于 const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' ); // 运行时编译为对象(React 元素) const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world' } }; ``` ## Rendering Elements Elements are the smallest building blocks of React apps. 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. Elements are what components are "made of". ### Rendering an Element into the DOM To render a React element into a root DOM node, pass both to ReactDOM.render() ``` const element =

Hello, world

; ReactDOM.render( element, document.getElementById('root') ); ``` ### Updating the Rendered Element React elements are immutable. Once you create an element, you can't change its children or attributes. An element is like a single frame in a movie: it represents the UI at a certain point in time. With our knowledge so far, the only way to update the UI is to create a new element, and pass it to ReactDOM.render(). In practice, most React apps only call ReactDOM.render() once. In the next sections we will learn how such code gets encapsulated into stateful components. ### 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. ## Components and Props Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called "props") and return React elements describing what should appear on the screen. ### Functional and Class Components The simplest way to define a component is to write a JavaScript function: ``` function Welcome(props) { return

Hello, {props.name}

; } ``` This function is a valid React component because it accepts a single "props" object argument with data and returns a React element. We call such components "functional" because they are literally JavaScript functions. You can also use an ES6 class to define a component: ``` class Welcome extends React.Component { render() { return

Hello, {this.props.name}

; } } ``` Classes have some additional features that we will discuss in the next sections. ### Rendering a Component ``` function Welcome(props) { return

Hello, {props.name}

; } const element = ; ReactDOM.render(element, document.getElementById('root')); ``` 1. We call `ReactDOM.render()` with the `` element. 2. React calls the `Welcome` component with `{name: 'Sara'}` as the props. 3. Our `Welcome` component returns a `

Hello, Sara

` element as the result. 4. React DOM efficiently updates the DOM to match `

Hello, Sara

`. > Always start component names with a capital letter. For example, `
` represents a DOM tag, but `` represents a component and requires `Welcome` to be in scope. ### Props are Read-Only Whether you declare a component as a function or a class, it must never modify its own props. 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. In the next section, 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. ### Default Prop Values 这部分从 typechecking-with-proptypes.html 找出来的, You can define default values for your props by assigning to the special `defaultProps` property: ``` class Greeting extends React.Component { render() { return

Hello, {this.props.name}

; } } Greeting.defaultProps = {name: 'Stranger'}; // Specifies the default values for props: ReactDOM.render(, document.getElementById('example')); ``` The `defaultProps` will be used to ensure that `this.props.name` will have a value if it was not specified by the parent component. The `propTypes` typechecking happens after `defaultProps` are resolved, so typechecking will also apply to the `defaultProps`. ## State and Lifecycle ``` class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval(() => this.tick(), 1000); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({date: new Date()}); } render() { return (

Hello, world!

It is {this.state.date.toLocaleTimeString()}.

); } } ReactDOM.render(, document.getElementById('root')); ``` Let's quickly recap what's going on and the order in which the methods are called: 1. When `` is passed to `ReactDOM.render()`, React calls the constructor of the `Clock` component. Since `Clock` needs to display the current time, it initializes `this.state` with an object including the current time. 2. React then calls the `Clock` component's `render()` method. This is how React learns what should be displayed on the screen. React then updates the DOM to match the `Clock`'s render output. 3. When the `Clock` output is inserted in the DOM, React calls the `componentDidMount()` lifecycle hook. 4. Every second the browser calls the `tick()` method. Inside it, the `Clock` component schedules a UI update by calling `setState()` with an object containing the current time. Thanks to the `setState()` call, React knows the state has changed, and calls `render()` method again to learn what should be on the screen. This time, `this.state.date` in the `render()` method will be different, and so the render output will include the updated time. React updates the DOM accordingly. 5. If the `Clock` component is ever removed from the DOM, React calls the `componentWillUnmount()` lifecycle hook so the timer is stopped. ### Using State Correctly There are three things you should know about setState(). #### Do Not Modify State Directly 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. #### State Updates May Be Asynchronous 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: ``` // Wrong 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. That 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((prevState, props) => ({ counter: prevState.counter + props.increment })); ``` #### State Updates are Merged When you call setState(), React merges the object you provide into the current state. 合并而非替换 ### The Data Flows Down A component may choose to pass its state down as props to its child components. 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. ## Handling Events Handling events with React elements is very similar to handling events on DOM elements. There are some syntactic differences: * React events are named using camelCase, rather than lowercase. * With JSX you pass a function as the event handler, rather than a string. ``` // HTML // JSX ``` Another difference is that you cannot return `false` to prevent default behavior in React. You must call `preventDefault` explicitly. 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 ES6 class, a common pattern is for an event handler to be a method on the class. 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.handleClick and pass it to onClick, `this` will be undefined when the function is actually called. ``` class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; // This binding is necessary to make `this` work in the callback 绑定不能少 this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); } render() { return ( ); } } ReactDOM.render( , document.getElementById('root') ); ``` ## Conditional Rendering Conditional rendering in React works the same way conditions work in JavaScript. Use JavaScript operators like `if` or the conditional operator to create elements representing the current state, and let React update the UI to match them. ``` function UserGreeting(props) { return

Welcome back!

; } function GuestGreeting(props) { return

Please sign up.

; } function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return ; } return ; } ``` ### Element Variables 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. ``` 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 = null; if (isLoggedIn) { button = ; } else { button = ; } return (
{button /* 这里是重点 */}
); } } ReactDOM.render( , document.getElementById('root') ); ``` ### Inline If with Logical && Operator ``` function Mailbox(props) { const unreadMessages = props.unreadMessages; return (

Hello!

{ unreadMessages.length > 0 &&

You have {unreadMessages.length} unread messages.

}
); } const messages = ['React', 'Re: React', 'Re:Re: React']; ReactDOM.render( , document.getElementById('root') ); ``` ### Inline If-Else with Conditional Operator ``` render() { const isLoggedIn = this.state.isLoggedIn; return (
{ isLoggedIn ? ( ) : ( ) }
); } ``` ### Preventing Component from Rendering ``` function WarningBanner(props) { if (!props.warn) { return null; } return (
Warning!
); } ``` Returning `null` from a component's `render` method does not affect the firing of the component's lifecycle methods. For instance, `componentWillUpdate` and `componentDidUpdate` will still be called. ## Lists and Keys ### Rendering Multiple Components ``` const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) =>
  • {number}
  • ); ReactDOM.render(
      {listItems}
    , document.getElementById('root') ); ``` ### Basic List Component ``` function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) =>
  • { /* 注意这里的 key */ } {number}
  • ); return (
      {listItems}
    ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( , document.getElementById('root') ); ``` ### Keys Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity. ### Extracting Components with Keys Keys only make sense in the context of the surrounding array. For example, if you extract a `ListItem` component, you should keep the key on the `` elements in the array rather than on the root `
  • ` element in the ListItem itself. ``` function ListItem(props) { const value = props.value; return ( // Wrong! There is no need to specify the key here:
  • {value}
  • ); } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Wrong! The key should have been specified here: ); return (
      {listItems}
    ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( , document.getElementById('root') ); ``` ### Keys Must Only Be Unique Among Siblings ### Embedding map() in JSX In the examples above we declared a separate `listItems` variable and included it in JSX. JSX allows embedding any expressions in curly braces so we could inline the map() result: ``` function NumberList(props) { const numbers = props.numbers; return (
      {numbers.map((number) => )}
    ); } ``` ## Forms ### Controlled Components In HTML, form elements such as ``, ` ``` ``` class EssayForm extends React.Component { constructor(props) { super(props); this.state = { inputValue: '', textValue: 'Please write an essay about your favorite DOM element.', selectValue: 'coconut' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleInputChange(event) { const name = event.target.name + 'Value'; this.setState({[name]: event.target.value}); // 使用了 ES6 特性 computed property name } handleSubmit(event) { alert('An essay was submitted.'); event.preventDefault(); } render() { return (