This article is included in github github.com/Michael-lzg...
Characteristics of React
- Use JSX syntax to create components, realize component-based development, and open the door for functional UI programming
- The high performance is praised: the efficient update of view is realized through diff algorithm and virtual DOM
Why use React
- The use of component-based development is in line with the trend of modern Web development
- Mature technology, perfect community and complete accessories, suitable for large-scale Web projects (sound ecosystem)
- Maintained by Facebook's dedicated team, the technical support is reliable
- ReactNative - Learn once, write anywhere: Build mobile apps with React
- It is easy to use and has very high performance. It supports server-side rendering
- React is very popular. From a technical point of view, it can satisfy curiosity and improve the technical level; From a professional perspective, it is conducive to job hunting and promotion and participation in projects with great potential
There are two ways to create components
- Created by JS function (stateless component)
- Create through class (stateful component)
JS function creation
- The function name must start with a capital letter. React uses this feature to determine whether it is a component
- The function must have a return value, which can be JSX object or null
- There must be one JSX element returned
- The return value of the component is wrapped in () to avoid line wrapping
function LearningList(props) { return ( <div className="list"> <h1>LearningList for {props.name}</h1> <ul> <li>Vue</li> <li>React</li> <li>Angular</li> </ul> </div> ) } ReactDOM.render(<Welcome name="lzg" />, document.getElementById('app'))
class creation
In es6, class is just a syntax sugar, not a real class. In essence, it is inherited by constructor + prototype implementation
class LearningList extends React.Component { constructor(props) { super(props) } // The component created by class must have a render method and display return, a react object or null render() { return ( <div className="list"> <h1>LearningList for {props.name}</h1> <ul> <li>Vue</li> <li>React</li> <li>Angular</li> </ul> </div> ) } }
jsx syntax
jsx syntax is a JavaScript syntax extension, which can be easily used to describe the UI in React. For example, the following is a jsx syntax
const element = <h1>Hello, world!</h1>
The above code is essentially equivalent to:
var element = React.createElement('h1', null, 'Hello, world!')
Writing standard of jsx
- The top layer of jsx can only have one root element, so we often wrap a div (or use Fragment) in the outer layer
- Tags in jsx can be single tags or double tags; If it is a single label, it must end with / >
- The outer layer of jsx is wrapped with a small bracket (), which is easy to read, and jsx can wrap lines
- Within {}, you can write any code that conforms to JS specification; If you want to write a comment, the comment must be placed inside {}
Embedded expressions in jsx
In jsx syntax, you can put any valid JavaScript expression within braces, which can be
- Operation expression
- Ternary operator
- Execute a function
class App extends React.Component { constructor(props) { super(props) this.state = { firstName: 'kobe', lastName: 'bryant', age: 20, } } sayHello(name) { return 'Hello ' + name } render() { return ( <div> <h2>{this.state.firstName + ' ' + this.state.lastName}</h2> <h2>{this.state.age >= 18 ? 'adult' : 'juveniles'}</h2> <h2>{this.sayHello('lzg')}</h2> </div> ) } }
jsx conditional rendering
1. Rendering of one of two components
class HelloMessage extends React.Component { render() { let userMessage if (this.props.loggedIn) { userMessage = ( <h1>Welcome back!</h1> ) } else { userMessage = ( <h1>Please sign up.</h1>; ) } return ( <div> <h1>My Super React App</h1> {userMessage} </div> ) } }
2. Rendering of a component with or without
function MessageList(props) { const unreadMessages = props.unreadMessages return ( <div> <h1>Hello!</h1> {unreadMessages.length > 0 && <h2>You have {unreadMessages.length} unread messages.</h2>} </div> ) }
jsx list loop
In jsx syntax, circular rendering uses the traversal map() method of the array to return a collection.
When traversing, there must be a unique index key to improve the efficiency of traversal. The key of an element should preferably be a unique string owned by the element in the list. Index can be used as a last resort.
class Admin extends Component { constructor(props) { super(props) this.state = { menus: [ { icon: require('../imag/home/ic_noti_block@2x.png'), title: 'Menu 1' }, { icon: require('../imag/home/ic_noti_block@2x.png'), title: 'Menu 2' }, { icon: require('../imag/home/ic_noti_block@2x.png'), title: 'Menu 3' }, { icon: require('../imag/home/ic_noti_block@2x.png'), title: 'Menu 4' }, ], } } renderList(value, index) { return ( <li key={index}> <p>Zhang San</p> <p>18 year</p> </li> ) } render() { return ( <div> <ul> {[1, 2, 3, 4, 5].map((value, index) => { return this.renderList(value, index) })} </ul> <ul> {this.state.menus.map((value, index) => { return ( <li key={index}> <img src={value.icon} width="30" /> <div>{value.title}</div> </li> ) })} </ul> </div> ) } }
Receive data props
If we want to pass values between components, the props attribute plays this role. Each component of react can accept a props parameter, which is an object that contains all your configurations for this component.
characteristic
- React converts the attributes passed to the component into an object and gives it to props
- Props is read-only. You cannot add or modify properties to props
function Person(props) { return ( <ul> <li>full name: {props.name}</li> <li>Age: {props.age}</li> </ul> ) } ReactDOM.render(<Welcome name="lzg" age="18" />, document.getElementById('app'))
Component state
If you need to define the custom attributes of a component, you need to define the state in the constructor constructor of the component
characteristic
- Only components created through class have state
- state is private and completely controlled by components
- Do not add unnecessary data in the render() method in state, which will affect the rendering performance!
- Do not call the setState() method in the render() method to modify the value of state
The difference between state and props
props is the external interface of the component, and state is the internal interface of the component. The main difference between the two: state is variable. It is a set of returned ui components maintained inside the component. props is a read-only attribute of the component. props cannot be modified directly in the component, but only in the upper layer of the component.
Create state
If you need to define custom properties of a component, define state in the constructor constructor of the component
class Mycom extends React.Component { constructor(props) { super(props) //Give this State assigns an object, and the attribute of the object is the custom attribute of the component this.state = { name: 'lzg', } } }
Modify state
You cannot directly modify the value of state, otherwise the data cannot drive the association. You need to use setState. The setState method receives a parameter, which is an object, similar to the native setData of the applet.
// Wrong way this.state.name = 'lzg' // Right way this.setState({ name: 'lzg' })
Use this The second form of setstate () is always safer because updated props and states are asynchronous. Here, we update the status based on these props.
// Wrong way this.setState({ total: this.state.total + this.props.count, }) // Right way this.setState((state, props) => { total: state.total + props.count })
In addition, setState can also receive the second parameter, which is a callback function
this.setState( { name: 'lzg', }, () => { console.log('state The value is modified successfully. The current value name Value is' + this.state.name) } )
Why can't you modify state directly? Why should you set state? setState does more than just modify this The value of state. In addition, the most important thing is that it will trigger the update mechanism of React, diff, and then update the patch part to the real dom.
Event binding
1. bind this when calling
class Foo extends React.Component { handleClick() { this.setState({ name: 'lzg' }) } render() { return <button onClick={this.handleClick.bind(this)}>Click me</button> } }
2. Bind this with bind in constructor
class Foo extends React.Component { constuctor(props) { super(props) this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState({ name: 'lzg' }) } render() { return <button onClick={this.handleClick}>Click me</button> } }
3. Bind this using the arrow function
class Foo extends React.Component { handleClick() { this.setState({ name: 'lzg' }) } render() { return <button onClick={(e) => this.handleClick(e)}>Click me</button> } }
4. public class fields
class Foo extends React.Component { handleClick = () => { this.setState({ name: 'lzg' }) } render() { return <button onClick={this.handleClick}>Click me</button> } }
react style
- Direct write in line style:
export const Footer = () => { return <div style={{{color:'orange', fontSize:'12px'}}>All Rights Reserved 2019</div> }
- Extract as object form
import React from 'react' const footerStyle = { backgroundColor: 'green', fontSize: '12px', color: 'orange', fontWeight: 'bold', } export const Footer = () => { return <div style={footerStyle}>All Rights Reserved 2019</div> }
- Use style sheets to define styles:
import '../css/comment.css' export const Footer = () => { return <div className="footer">All Rights Reserved 2019</div> }
Life cycle function
The life cycle of a component consists of three phases: Mounting, Updating, and Unmounting
-
Mounting calls the following functions in turn
- Constructor (): constructor of ES6 class (to initialize state or bind this)
- Getinitialstate(): initialize state in Es5.
- Getdefaultprops(): initialize props in Es5. Use the defaultProps() method in ES6.
- componentWillMount(): called before the component is mounted. Execute only once.
- render(): to render a component, you must implement this method.
- componentDidMount(): called after the component is loaded. At this time, the real DOM node has been generated. Execute only once.
-
Updating calls the following functions in turn
- This method is triggered before the componentWillReceiveProps() component receives new props
- shouldComponentUpdate() determines whether to re render the component according to the return value of this method, and returns true to re render, otherwise it will not render
- componentWillUpdate() component will be updated
- render() re renders the component, which is the same function as render in the Mounting stage
- componentDidUpdate() component has been updated
-
Unmounting
- componentWillUnmount() uninstall the component; Clear timer, clear dom
PropTypes
Over time, applications get larger and larger, so type checking is very important. PropTypes provides type checking for components and provides good documentation for other developers. If the react project does not use Typescript, it is recommended to add PropTypes to the component.
// Old writing class PropTypeOne extends React.Component { render() { return ( <div> <div>{this.props.name}</div> <div>{this.props.email}</div> </div> ) } } PropTypeOne.propTypes = { name: PropTypes.string, email: function (props, propName, componentName) { if (!/^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/.test(props[propName])) { return new Error('assembly' + componentName + 'Properties in' + propName + 'Does not conform to the format of the mailbox') } }, } // New writing class PropTypeTwo extends React.Component { static propTypes = { name: PropTypes.string, } render() { return ( <div> <div>{this.props.name}</div> </div> ) } }
When the incoming prop value type is incorrect, the JavaScript console will display a warning. For performance reasons, propTypes is only checked in development mode.
You can define the default value of props by configuring the specific defaultProps property:
class Greeting extends React.Component { render() { return <h1>Hello, {this.props.name}</h1> } } // Specify the default value of props: Greeting.defaultProps = { name: 'Stranger', } // Render "Hello, Stranger": ReactDOM.render(<Greeting />, document.getElementById('app'))
Controlled and uncontrolled components
Controlled components
We should often use forms to collect user input. For example, elements such as < input > < Select > < textarea > should be bound with a change event. When the state of the form changes, the onChange event will be triggered to update the state of the component. This component is called a controlled component in react. In a controlled component, the state rendered by the component corresponds to its value or checked attribute. React eliminates the local state of the component in this way and makes the whole state controllable. React officials also recommend using controlled form components.
import React, { Component } from 'react' export default class MyInput extends Component { handleContentChange = (e) => { this.setState({ content: e.target.value, }) } render() { return ( <div> <input type="text" value={this.state.value} onChange={this.handleContentChange} /> </div> ) } }
Process of updating state of controlled components:
- You can set the default value of the form in the initial state
- The onChange event handler is called whenever the value of the form changes
- The event processor obtains the changed state through the event object e and updates the state of the component
- Once the state is updated through the setState method, it will trigger the re rendering of the view and complete the update of the form component
In react, data flows individually. From the example, we can see that the data of the form comes from the state of the component and is passed in through props, which is also called one-way data binding. Then we write the new data back to the state through the onChange event handler to complete the two-way data binding.
Uncontrolled components
If a form component does not have value props (radio and check buttons correspond to checked props), it can be called an uncontrolled component In the uncontrolled component, we can use a ref to get the form value from the DOM. Instead of writing an event handler for each status update.
class NameForm extends React.Component { constructor(props) { super(props) this.handleSubmit = this.handleSubmit.bind(this) } handleSubmit(event) { alert('A name was submitted: ' + this.input.value) event.preventDefault() } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" ref={(input) => (this.input = input)} /> </label> <input type="submit" value="Submit" /> </form> ) } }
ref
React supports a very special attribute Ref, which you can use to bind to any component of render() output.
String usage
Through this Refs ['inputref '] to access
<input ref="inputRef" />
ref as callback function
class AutoFocusTextInput extends Component { componentDidMount(){ this.textInput.focus(); } render(){ return ( <Input ref={(input) => { this.textInput = input }}> ) } }
The ref callback function of the parent component can use the DOM of the child component.
function CustomTextInput(props) { return ( <div> <input ref={props.inputRef} /> </div> ) } class Parent extends React.Component { render() { return <CustomTextInput inputRef={(el) => (this.inputElement = el)} /> } }
React.createRef()
After react version 16.3, use this method to create refs. Assign it to a variable, mount it on the dom node or component through ref, and the current attribute of the ref will get the instance of the dom node or component
class Child extends React.Component { constructor(props) { super(props) this.myRef = React.createRef() } componentDidMount() { console.log(this.myRef.current) } render() { return <input ref={this.myRef} /> } }
react-router
React router DOM is a library of routes in an application. There is no routing function in the react library, so the react router DOM needs to be installed separately.
React router DOM provides two routers, browserouter and hashroauer. The former is based on the pathname segment of url, and the latter is based on the hash segment.
Basic usage:
npm install react-router-dom --save
import { BrowserRouter, Route, Link, Redirect } from 'react-router-dom' class MyRouter extends React.Component { render() { return ( <BrowserRouter> <Link to="/">router1</Link> <Link to="/router2">router2</Link> <Link to="/router3">router3</Link> <hr /> <Redirect exact from="/" to="/router1" /> <Route path="/router1" component={router1}></Route> <Route path="/router2" component={router2}></Route> <Route path="/router3" component={router3}></Route> </BrowserRouter> ) } }
Route jump
1. Jump with Link tag
import { BrowserRouter, Route, Link, Redirect } from 'react-router-dom' class MyRouter extends React.Component { render() { return ( <BrowserRouter> <Link to="/">router1</Link> <Link to="/router2">router2</Link> <Link to="/router3">router3</Link> <hr /> <Redirect exact from="/" to="/router1" /> <Route path="/router1" component={router1}></Route> <Route path="/router2" component={router2}></Route> <Route path="/router3" component={router3}></Route> </BrowserRouter> ) } }
2. Programming navigation
- The routing component can be directly from this props. Get history from history
- The non routing component cannot get the history directly. It needs to cooperate with withRouter
this.props.history.push(url) this.props.history.go(-1)
Routing parameters
1.params
<Route path='/path/:name' component={Path}/> <link to="/path/123">xxx</Link> this.props.history.push({pathname:"/path/" + name}); // For reading parameters: this props. match. params. name
2.query
<Route path='/query' component={Query}/> <Link to={{ pathname : '/query' , query : { name : 'sunny' }}}></Link> this.props.history.push({pathname:"/query",query: { name : 'sunny' }}); // For reading parameters: this props. location. query. name
3.state
<Route path='/sort ' component={Sort}/> <Link to={{ pathname : '/sort ' , state : { name : 'sunny' }}}></Link> this.props.history.push({pathname:"/sort ",state : { name : 'sunny' }}); // For reading parameters: this props. location. query. state
4.search
<Route path='/web/search ' component={Search}/> <link to="web/search?id=12121212">xxx</Link> this.props.history.push({pathname:`/web/search?id ${row.id}`}); // For reading parameters: this props. location. search
Route guard
The Route Component can receive a Component component. When the path matches, the Route Component will be rendered. We can also do something after path matching, which is similar to the routing guard in Vue.
The Route Component is still used, but this time the Component does not pass data through the Component, but through the render attribute.
import { Route } from 'react-router-dom' function Custom() { return ( <Route path="/index" Render={() => { //isLogin determines whether the user logs in. If he logs in to the rendering home page, he does not log in to the rendering login if (isLogin) { return <Index></Index> } else { return <Login></Login> } }} /> ) }
withRouter
withRouter in high-level components is used to wrap a component into the Route, and then the three objects history, location and match of react router will be put into the props attribute of this component.
By default, only components rendered by route matching can exist this Props, you can have routing parameters, use the writing method of programmed navigation, and execute this props. history. Push ('/ detail') jumps to the page of the corresponding route. However, not all components are directly connected to the route (jump to this component through the route). When these components need routing parameters, you can use withRouter to pass in routing parameters to this component. At this time, you can use this props.
import React,{Component} from 'react' import {Switch,Route,NavLink,Redirect,withRouter} from 'react-router-dom' //Introducing withRouter import One from './One' import NotFound from './NotFound' class App extends Component{ //Only then can we get this Props, including three objects (history, match, location) console.log(this.props); //Output {match: {...}, location: {...}, history: {...}, etc.} render(){ return (<div className='app'> <NavLink to='/one/users'>User list</NavLink> <NavLink to='/one/companies'>Company list</NavLink> <Switch> <Route path='/one/:type?' component={One} /> <Redirect from='/' to='/one' exact /> <Route component={NotFound} /> </Switch> </div>) } } export default withRouter(App); //Here we need to execute WithRouter
Recommended articles
Talking about data state management and realizing a simple version of vuex
Summarize 18 webpack plug-ins, there will always be what you want!
Build a vue-cli4+webpack mobile terminal framework (out of the box)
From zero construction to optimization of a Vue cli like scaffold
Encapsulate a toast and dialog component and publish it to npm
Build a webpack project from scratch
Summarize several methods of webpack packaging optimization
Advanced application of summarizing vue knowledge system
Summarize the practical skills of vue knowledge system
Introduction to summarizing vue knowledge system
Summarize the common skills of H5 development of mobile terminal (full of dry goods!)