This is how I learned React with Shang Silicon Valley recently. Some of the words in it are the teacher’s remarks. I just sorted out what I learned and the teacher’s information according to my favorite method, so that I could quickly check the information in the development project.

There are two ways to define a component

Functional components and class components, two methods

Functional component instance

Function MyComponent(){console.log(this); function MyComponent(){console.log(this); // this is undefined because Babel is compiled in strict mode. Return <h2> I am using a function defined component (for simple components)</h2>} //2. Render component to page reactdom.render (<MyComponent/>, document.getelementbyid ('test')) /* Execute reactdom.render (<MyComponent/>....... After that, what happened? 1.React parses the component tag and finds MyComponent. 2. After discovering that the component is defined using a function, call this function to convert the returned virtual DOM into the real DOM and render it on the page. * /Copy the code

Class component instance

Class MyComponent extends React.Component {render(){render(){render(); -- on the MyComponent prototype object for instance use. // Who is this in render? <=> MyComponent instance object. The console. The log (' in the render this: ', this); Return <h2> I am using the class defined component (for the definition of complex components)</h2>}} //2. Render component to page reactdom.render (<MyComponent/>, document.getelementbyid ('test')) /* Execute reactdom.render (<MyComponent/>....... After that, what happened? 1.React parses the component tag and finds MyComponent. 2. Discover that the component is defined using a class, then new the instance of that class, and call the render method on the prototype through that instance. 3. Turn the virtual DOM returned by render into the real DOM and render it on the page. * /Copy the code

Three properties of a component instance

State indicates the initialization state, props, and refs

The state instance

State = {isHot:false,wind:' breeze '} render(){const {isHot,wind} = This. state return <h1 onClick={this.changeWeather}> Today the weather is {isHot? 'Hot' : 'cool '}, ChangeWeather = ()=>{const isHot = this.state.ishot this.setState({isHot:! Reactdom.render (<Weather/>, document.getelementbyId ('test'))}Copy the code

Props instance

1props Basic use

Class Person extends React.Component{render(){// console.log(this); Const {name,age,sex} = this. Props return (<ul> <li> name: {name}</li> <li> gender: {sex}</li> <li> age: Render (<Person name="jerry" age={19}) Male sex = "" / >, the document. The getElementById (" test"))Copy the code

2 Restrictions on props via a plugin for propTypes

Class Person extends React.Component{render(){// console.log(this); Const {name,age,sex} = this. Props //props is read-only //this. Props. Name = 'jack' //this. Gender: {sex}</li> <li> Age: {the age + 1} < / li > < / ul >)}} / / the limitation on the label attribute types, necessity Person. PropTypes = {name: propTypes. String. IsRequired, / / name will pass, String,// restrict sex to string age: proptypes. number,// restrict age to numeric value speak: proptypes. func,// restrict speak to function} // Specify default tag attribute values Person. DefaultProps ={sex:' male ',//sex defaults to male age:18 //age defaults to 18} // Render component to page reactdom. render(<Person name={100}) Speak ={speak}/>, document.getelementById ('test')) function speak(){console.log(' I spoke '); }Copy the code

Short for 3props

Class Person extends React.Component{constructor(props){// Whether the constructor receives props, and whether it passes to super, depends on: If you want this in the constructor to access props // console.log(props); super(props) console.log('constructor',this.props); } / / the limitation on the label attribute types, necessity static propTypes = {name: propTypes. String. IsRequired, / / name will pass, Sex: proptypes. string,// limit sex to a string age: proptypes. number,// limit age to a number} // Specify the default tag attribute value static defaultProps = { Render (){// console.log(this); render(){// console.log(this); Const {name,age,sex} = this. Props //props is read-only return (<ul> <li> name: {name}</li> <li> Gender: {sex}</li> <li> Age: <Person name="jerry"/>, document.getelementbyid ('test1'));Copy the code

4 Function components use props

Function Person (props){const {name,age,sex} = props return (<ul> <li> name: {name}</li> <li> Sex: {sex}</li> age: {the age} < / li > < / ul >)} Person. PropTypes = {name: propTypes. String. IsRequired, / / name will pass, Sex: proptypes. string,// limit sex to a string age: proptypes. number,// limit age to a number} // Specify the default tag attribute value person. defaultProps = { // Render the component to the page reactdom.render (<Person name="jerry"/>,document.getElementById('test1'))Copy the code

Refs instance

1 The ref is a string

ShowData = ()=>{const {input1} = this.refs alert(input1.value) ShowData2 = ()=>{const {input2} = this.refs alert(input2.value)} render(){return(<div> <input) Ref ="input1" type="text" placeholder=" placeholder "; <button onClick={this.showData}> </button>&nbsp; <input ref="input2" onBlur={this.showData2} type="text" placeholder=" lost focus prompt data "/> </div>)}} // Render components to the page ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))Copy the code

2 callback function form

Class Demo extends react.ponent {showData = ()=>{const {input1} = this alert(input1.value)} ShowData2 = ()=>{const {input2} = this alert(input2.value)} render(){return(<div> <input ref={c => This. input1 = c} type="text" placeholder=" placeholder "/>&nbsp; <button onClick={this.showData}> </button>&nbsp; <input onBlur={this.showData2} ref={c => this.input2 = c} type="text" placeholder=" placeholder "/>&nbsp; </div>)} // Render component to page reactdom.render (<Demo a="1" b="2"/>, document.getelementById ('test'))Copy the code

3 The number of times the callback is executed in callback REF

Class Demo extends React.Component{state = {isHot:false} showInfo = ()=>{const {input1} = this Alert (input1.value)} changeWeather = ()=>{// Get the original state const {isHot} = this.state // Update the state this.setState({isHot:! isHot}) } saveInput = (c)=>{ this.input1 = c; console.log('@',c); } render(){const {isHot} = this.state return(<div> <h2> weather is very {isHot? </h2> <input ref={this.saveInput} type="text"/><br/><br/> <br/>< button onClick={this.showInfo}> <button onClick={this.changeWeather}> I switch weather </button> </div>)}} // render component to page ReactDOM.render(<Demo/>,document.getElementById('test'))Copy the code

The life cycle is divided into three phases

Initialization phase

Triggered by reactdom.render () — initial render

  1. constructor()
  2. getDerivedStateFromProps()
  3. render()
  4. ComponentDidMount () =====> componentDidMount

This hook is used for initialization, such as starting timers, sending network requests, and subscribing to messages

Update the stage

Triggered by rerender within the component this.setsate () or the parent component

  1. getDerivedStateFromProps()
  2. shouldComponentUpdate()
  3. Render () =====> One that must be used
  4. getSnapshotBeforeUpdate()
  5. componentDidUpdate()

Uninstall the component

Triggered by ReactDOM. UnmountComponentAtNode ()

  1. ComponentWillUnmount () =====

This is where you do some finishing touches, such as turning off timers and unsubscribing messages

Common life cycle instances

componentDidMount

class Time extends React.Component { state = {date: new Date()} componentDidMount () { setInterval(() => { this.setState({ date: New Date()})}, 1000)} render () {return (<div> <h1>hello</h1> <input type="text"/> <span> {this.state.date.toTimeString()} <input type="text"/> </span> </div> ) } } ReactDOM.render(<Time/>,document.getElementById('test'))Copy the code

ComponentWillUnmount instance

Class Count extends componentWillUnmount(){console.log('Count-- --componentWillUnmount'); } / / unloading components button callback death = () = > {ReactDOM. UnmountComponentAtNode (document. GetElementById () 'test')} render () {return (< div > <button onClick={this.death}> Uninstall component </button> </div>)}}Copy the code

Mouse events

OnClick click event, onMouseEnter move in event, onMouseLeave move out event

render() { return ( <li style={{backgroundColor: mouse? '#ddd': 'white'}} onMouseEnter={this.handleMouse(true)} onMouseLeave={this.handleMouse(false)} > <label> <input type="checkbox" checked={done} onChange={this.handleCheck(id)} /> <span>{name}</span> </label> <button onClick={()=>this.handleDelete(id)} className="btn btn-danger" style={{display:mouse? </button> </li>)}Copy the code

Keyboard events

Are the onKeyUp

Render () {return (<div className="todo-header"> <input onKeyUp={this.handleKeyup} type="text" placeholder=" render() {return (<div className="todo-header"> <input onKeyUp={this.handleKeyup} type="text" placeholder=" Press Enter to confirm "/> </div>)}Copy the code

The input event

These are onChange events

<input onKeyUp={this.handleKeyUp} type="text" placeholder=" Press Enter to confirm "/> <input type="checkbox" checked={done} onChange={this.handlecheck (id)} />Copy the code

Input Gets the input

Refs callback function form

Export the default class Search extends Component {Search () = = > {/ / / / get the user input the console. The log (value) this. KeyWordElement. / / Const {value} = this.keyWordElement const {value} = this.keyWordElement {value:keyWord}} = this render() { return ( <section className="jumbotron"> <input ref={c=>this.keyWordElement = c} Type ="text" placeholder=" placeholder "/>&nbsp; </section> ) } }Copy the code

Keyboard format Event format

HandleKeyUp = (event)=>{const {keyCode,target} = event If (target.value.trim() === ''){alert(' name must not be empty ') return} const todoObj = {id: nanoid(),name: target.value,done: } // Give todoObj to addTodo this.props. AddTodo (todoObj) // Empty the input target.value = ""} <input onKeyUp={this.handleKeyUp} Type ="text" placeholder=" please input your task name, press Enter to confirm "/>Copy the code

The checkbox form uses the onChange method

/ / check, HandleCheck = (id) => {return (event) => {this.props. UpdateTodo (ID,event.target.checked)}} render() { const {done} = this.props return ( <li> <label> <input type="checkbox" checked={done} onChange={this.handleCheck(id)} /> </label> </li> ) }Copy the code

Parent-child communication

1. Parent component passes data to parent component: props passes data to parent component: props passes data to parent component: props passes data to parent component: requires the parent to pass a function to its child in advance

Message subscription and publishing mechanism

Is via a plug-in called Pubsub-js

1. Subscribe first, publish later (understand: have a kind of telegraphic dialogue feeling) 2. To unsubscribe from the component’s componentWillUnmount

Sibling component communication cases

A component

import React, { Component } from 'react' import PubSub from 'pubsub-js' import './index.css' export default class List extends Component {// Initialization state = {users:[], isFirst: true, isLoading: false, err: } // componentDidMount(){this.token = subscribe('atguigu',(MSG,stateObj) =>{console.log(' received data ',stateObj);  this.setState(stateObj) }) } componentWillUnmount(){ PubSub.unsubscribe(this.token) } }Copy the code

Component B sends a subscription when it clicks search

import React, { Component } from 'react' import PubSub from 'pubsub-js' import axios from 'axios' export default class Search extends Component {search = () =>{// Publish ('atguigu',{isFirst: false,isLoading: true}) // console.log(keyWord) } render() { return ( <section className="jumbotron"> <h3 <button onClick={this.search}> </button> </div> </section>)}}Copy the code

routing

Basic use of routing

2. Change the a label in the navigation area to Link <Link to="/ XXXXX ">Demo</Link> 3. <Route path='/ XXXX 'Component ={Demo}/> 4. The outermost part of <App> wraps a <BrowserRouter> or <HashRouter>Copy the code

Routing components versus generic components

Common components: <Demo/> Route components: <Route path="/ Demo "Component ={Demo}/> 2. Common component: Components Routing component: Pages 3. The props received are different: General component: Receives what is passed when writing component labels. Routing component: receives three fixed attributes history: go: ƒ go(n) goBack: ƒ goBack() goForward: ƒ goForward() push: ƒ push(path, state) replace: ƒ replace(path, state) location: pathName: "/about" search:" undefined match: params: {} path: "/about" url: "/about"Copy the code

NavLink and encapsulation NavLink

Install a plugin called react-router-dom

npm i react-router-dom

1.NavLink can implement route link highlighting, using activeClassName to specify the style name

NavLink instance

<NavLink activeClassName="atguigu" className="list-group-item" to="/about">About</NavLink>
<NavLink activeClassName="atguigu" className="list-group-item" to="/home">Home</NavLink>
Copy the code

Encapsulate NavLink instances

import React, {Component} from 'react' import {Route} from 'react-router-dom' import Home from './pages/Home' //Home is the Route Component import About from './pages/About' //About is a routing component Import Header from './components/Header' //Header is a general component import MyNavLink from './components/MyNavLink' export default class App extends Component { render() { return ( <div> <div className="row"> <div className="col-xs-offset-2 col-xs-8"> <Header/> </div> </div> <div className="row"> <div className="col-xs-2 Col-xs-offset-2 "> <div className="list-group"> <div className="list-group" to="/about">About</MyNavLink> <MyNavLink to="/home">Home</MyNavLink> </div> </div> <div className="col-xs-6"> <div ClassName ="panel"> <div className="panel-body"> {/* Register Route */} <Route path="/about" component={about}/> <Route path="/home" component={Home}/> </div> </div> </div> </div> </div> ) } }Copy the code

MyNavLink components

import React, { Component } from 'react' import {NavLink} from 'react-router-dom' export default class MyNavLink extends Component { render() { // console.log(this.props); return ( <NavLink activeClassName="atguigu" className="list-group-item" {... this.props}/> ) } }Copy the code

The use of the Switch

1. Typically, there is a one-to-one relationship between path and Component. 2.Switch improves route matching efficiency (single match). 3.’react-router-dom’ adds a Switch method

The switch instance

import React, {Component} from 'react' import {Route,Switch} from 'react-router-dom' import Home from './pages/Home' //Home is a routing Component Import About from './pages/About' //About is a routing component Import Header from './components/Header' //Header is a general component import MyNavLink from './components/MyNavLink' import Test from './pages/Test' export default class App extends Component { render() { return ( <div> <div className="row"> <div className="col-xs-offset-2 col-xs-8"> <Header/> </div> </div> <div ClassName ="row"> <div className="col-xs-2 col-xs-offset-2"> <div className="list-group" */} <MyNavLink to="/about">About</MyNavLink> <MyNavLink to="/home">Home</MyNavLink> </div> </div> <div ClassName =" col-XS-6 "> <div className="panel"> <div className="panel-body"> {/* Register Route */} <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Route path="/home" component={Test}/> </Switch> </div> </div> </div> </div> </div> ) } }Copy the code

Fix missing page style for multilevel path refresh

1. Public /index.html does not write./ write/(common) 2. Public /index.html does not write./ %PUBLIC_URL% (common) 3. Using HashRouter

Strict matching and fuzzy matching of routes

1. Fuzzy matching is used by default (simple note: [input path] must contain the paths to be matched, and the order must be consistent) <br> 2. Enable exact matching: <Route exact={true} path="/about" Component ={about}/><br> 3. Strict matching Do not enable strict matching. You need to enable strict matching again. In some cases, secondary routes cannot be matchedCopy the code

The use of the Redirect

1. It is written at the bottom of all route registrations. If all routes fail to match, route 2 specified by the Redirect is redirected. Specific code:  <Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch>Copy the code

Embedded routines by

When registering child routes, set the path value of the parent route. 2. Routes are matched according to the sequence of registered routes

import React, { Component } from 'react' import MyNavLink from '.. /.. /components/MyNavLink' import {Route,Switch,Redirect} from 'react-router-dom' import News from './News' import Message From './Message' export default class Home extends Component {render() {return (<div> <h3> <div> <ul className="nav nav-tabs"> <li> <MyNavLink to="/home/news">News</MyNavLink> </li> <li> <MyNavLink To ="/home/message"> message </MyNavLink> </li> </ul> {/* Register Route */} <Switch> <Route path="/home/news" component={news}/> <Route path="/home/message" component={Message}/> <Redirect to="/home/news"/> </Switch> </div> </div> ) } }Copy the code

Pass parameters to the routing component

Params: <Link to='/demo/test/ Tom /18'}> <Route path="/demo/test/:name/:age" Component ={test}/> <Link to='/demo/test? Name =tom&age=18'}> Details </Link> Register Route: <Route path="/demo/test" component={test} This. Props. Location. Note: the search for the string search is urlencoded coding, need to use the querystring resolution 3. The state parameters routing link (parameters) to carry: <Link to={{pathName :'/demo/test',state:{name:' Tom ',age:18}}}> < the Route path = "/ demo/test" component = {test} / > receive parameters: this. Props. Location. Note: the state refresh can also keep parametersCopy the code

Params parameter instance

Parent routing component

import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Detail from './Detail' export default Class Message extends Component {state = {messageArr:[{id:'01',title:' 1'}, {id:'02',title:' 2'}, {id: '03, title: news' 3'}, ] } render() { const {messageArr} = this.state return ( <div> <ul> { messageArr.map((msgObj)=>{ return ( <li Key ={msgobj.id}> {/* Pass the params parameter to the routing component */} <Link To = {` / home/message/detail / ${msgObj. Id} / ${msgObj. Title} `} > {msgObj. Title} < / Link > < / li >)})} < / ul > < hr / > {/ * statement received params parameters  */} <Route path="/home/message/detail/:id/:title" component={Detail}/> </div> ) } }Copy the code

Child routing components

Import React, {Component} from 'React' const DetailData = [{id:'01',content:' Hello, China '}, {id:'02',content:' Hello, }, {id:'03',content:' Hello, }] export default class Detail extends Component {render() {console.log(this.props); Const {id,title} = this.props.match. Params const findResult = detaildata.find ((detailObj)=>{return detailObj.id === id }) return ( <ul> <li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{findResult.content}</li> </ul> )}}Copy the code

2. The search parameters

Parent routing component

import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Detail from './Detail' export default Class Message extends Component {state = {messageArr:[{id:'01',title:' 1'}, {id:'02',title:' 2'}, {id: '03, title: news' 3'}, ] } render() { const {messageArr} = this.state return ( <div> <ul> { messageArr.map((msgObj)=>{ return ( <li Key ={msgobj.id}> {/* Pass the search parameter to the routing component */} <Link to={' /home/message-detail/? Id = ${msgObj. Id} & title = ${msgObj. Title} `} > {msgObj. Title} < / Link > < / li >)})} < / ul > < hr / > {/ * search parameters without declaration receiving, <Route path="/home/message/detail" component={detail}/> </div>)}}Copy the code

Child routing components

Import React, {Component} from 'React' const DetailData = [{id:'01',content:' Hello, China '}, {id:'02',content:' Hello, }, {id:'03',content:' Hello, }] export default class Detail extends Component {render() {console.log(this.props); Const {search} = this.props. Location const {id,title} = qs.parse(search.slice(1)) const findResult = DetailData.find((detailObj)=>{ return detailObj.id === id }) return ( <ul> <li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{findResult.content}</li> </ul> ) } }Copy the code

3. The state parameters

Parent routing component

import React, { Component } from 'react' import {Link,Route} from 'react-router-dom' import Detail from './Detail' export default Class Message extends Component {state = {messageArr:[{id:'01',title:' 1'}, {id:'02',title:' 2'}, {id: '03, title: news' 3'}, ] } render() { const {messageArr} = this.state return ( <div> <ul> { messageArr.map((msgObj)=>{ return ( <li Key ={msgobj.id}> {/* Passes the search parameter to the routing component */} <Link to={{pathname:'/home/message/detail',state:{id:msgObj.id,title:msgObj.title}}}>{msgObj.title}</Link> </li> ) }) } </ul> <Route path="/home/message/detail" component={detail}/> </div>)}}Copy the code

Child routing components

Import React, {Component} from 'React' const DetailData = [{id:'01',content:' Hello, China '}, {id:'02',content:' Hello, }, {id:'03',content:' Hello, }] export default class Detail extends Component {render() {console.log(this.props); / / receive the search parameters const {id, title} = this. Props. The location. The state | | {} const findResult = DetailData. Find ((detailObj) = > { return detailObj.id === id }) return ( <ul> <li>ID:{id}</li> <li>TITLE:{title}</li> <li>CONTENT:{findResult.content}</li> </ul> ) } }Copy the code

Push versus replace patterns

Replace: A-B-C Can be returned to the previous level. This method is applicable to users who do not need to return to the login page after login

<MyNavLink replace to="/about">About</MyNavLink>
<MyNavLink replace to="/home">Home</MyNavLink>
Copy the code

Programmatic routing navigation

With this. Prosp. History on the object API of routing jump, forward, backward operation – this. Prosp. History. Push () – this. Prosp. History. The replace () -this.prosp.history.goBack() -this.prosp.history.goForward() -this.prosp.history.go()

ReplaceShow = (id, title) = > {/ / / / replace jump + carry params parameters enclosing props. The history, the replace (` / home/message/detail / ${id} / ${title} `) / / replace the jump + / / search parameters to carry this. Props. History. The replace (` / home/message/detail? Id = ${id} & title = ${title} `) / / replace jump + state parameters to carry this. Props. History. The replace (` / home/message/detail `, {id, title})} pushShow ${id}/${title} '=>{// this.props.history. Push (' /home/message/detail/${id}/${title}') // this.props.history. Push (' /home/message/detail? Id =${id}&title=${title} ') //push + with state parameter this.props.history. Push (' /home/message/detail ',{id,title})} back = ()=>{ this.props.history.goBack() } forward = ()=>{ this.props.history.goForward() } go = ()=>{ this.props.history.go(-2) } <li key={msgobj.id}> <button onClick={()=> this.pushshow (msgobj.id, msgobj.title)}> This.replaceshow (msgobj.id, msgobj.title)}>replace </button> </button onClick={this.back}> <button onClick={this.forward}> </button>&nbsp; <button onClick={this.go}>go</button> </li>Copy the code

The use of withRouter

//withRouter can process generic components, giving generic components the same API as routing components. //withRouter returns a new component

import React, { Component } from 'react' import {withRouter} from 'react-router-dom' class Header extends Component { back = ()=>{ this.props.history.goBack() } forward = ()=>{ this.props.history.goForward() } go = ()=>{ this.props.history.go(-2) } Render () {console.log('Header component received props is ',this.props); render() {console.log('Header component received props is ',this.props); Return (<div className="page-header"> <h2>React Router Demo</h2> <button onClick={this.back}> <button onClick={this.forward}> </button>&nbsp; <button onClick={this.go}>go</button> </div> ) } } export default withRouter(Header)Copy the code

Differences between BrowserRouter and HashRouter

1. The underlying principles are different: BrowserRouter uses the H5 History API, which is incompatible with IE9 and later versions. A HashRouter uses a hash of a URL.

2. The path of BrowserRouter does not contain #, for example, localhost:3000/demo/test

3. Impact on the route State parameter after refreshing (1).BrowserRouter has no impact because state is stored in the history object. (2). The state parameter of the route is lost after the HashRouter is refreshed.

4. Note: The HashRouter can be used to solve some problems related to path errors.