I met
React is an open source JavaScript library that renders data into HTML views
The advantages of the React
- Componentized mode and declarative coding are adopted to improve development efficiency and component reuse rate
- React Native allows you to use the React syntax for mobile applications.
- Use virtual DOM + excellent Diffing algorithm to minimize interaction with real DOM and minimize page redrawing
Hello React
Babel.js is used to convert JS to JSX. UMD versions of React and ReactDOM are available via CDN.
The import order is to introduce the core library dom Babel
<! -- What a container -->
<div id="test"></div>
<! -- Introducing a core library -->
<script src=".. /react.development.js"></script>
<! React-dom is used to support the react operation.
<script src=".. /react-dom.development.js"></script>
<script src=".. /babel.min.js"></script>
<script type="text/babel"> // This must be written as Babel
// Create virtual DOM
const Virtual = ( // Do not use quotation marks here because this is the virtual DOM
<h1>hello,react</h1>
)
// Render the virtual DOM to the page
// reactdom.render (virtual DOM, container)
// reactdom.render (Virtual,"#test") //React does not provide such a syntax
ReactDOM.render(Virtual,document.getElementById('test'));
</script>
Copy the code
Js is different from JSX
Use JS to create the virtual DOMconst VDOM = React.createElement("h1, {id:"title"}, React.createElement("span")); Const Virtual = (
title"> )Copy the code
Virtual DOM annotation
const Virtual = (
<h1>
{ /* <span id="title"></span>*/ * * * * * * * * * * * * * * * *</h1>
)
const Virtual = (
<h1>
<span id="title"></span>
</h1>Virtual DOM is an object debuger test. Virtual DOM is an object debuger testCopy the code
JSX syntax rules javascript XML
Const VDOM = react. createElement(“h1, {id:”title”}, react. createElement(“span”));
{} —– what is an expression? What is a statement?
const myId = 'aTguiGu'
const myData = 'hello,ReaCt'
const Virtual = (
<h1 id={myId.toLocaleLowerCase()}>// Tags are mixed with js expressions using {}<span>{myData.toLocaleLowerCase()}</span>
</h1>
)
ReactDOM.render(Virtual,document.getElementById('test')); Expression a a+b demo(1)
arr.map()
function(){}
consti = ? An expression statement is one that connects valuesif() {}for() {}switch() {}constI = No value is connectedCopy the code
The JSX style class is called className because it conflicts with the JS class
const Virtual = ( // Do not use quotation marks here because this is the virtual DOM
<h1 className="title" id={myId.toLocaleLowerCase()}>
<span>{myData.toLocaleLowerCase()}</span>
</h1>
)
Copy the code
Sytle ={{key:value,key:value}}
const Virtual = ( // Do not use quotation marks here because this is the virtual DOM
<h1 className="title" id={myId.toLocaleLowerCase()}>
<span style={{color:'red',fontSize:'50px'}} >{myData.toLocaleLowerCase()}</span>
</h1>
)
Copy the code
There can be only one root tag. The tag must be closed
Label first letter
If it starts with a lowercase letter, the tag is converted to an element of the same name in HTML. If there is no corresponding element in HTML, an error is reported
If it starts with an uppercase letter, find the corresponding component directly
React will automatically iterate over arrays of values
React will automatically iterate through groups for you
const data = ['Angular'.'React'.'Vue']
const Virtual = (
<div>
<h1>The front frame</h1>
<ul>{data.map((item,index)=>{// Only return<li key={index}>{item}</li>})}</ul>
</div>
)
ReactDOM.render(Virtual,document.getElementById('test'));
Copy the code
Component-oriented programming
Install react Dev Tools
The console allows you to view components and test tools
Methods for defining components
Functional component
The function must have a return value hanging on the must be end tag
// Create functional components
function MyComponent() {
return <h2>I am a function defined component (for simple component definitions)</h2> // There must be a return value
}
// Must be the end tag
ReactDOM.render(<MyComponent/>.document.getElementById('test'));
Copy the code
Use of the class class
// Create a Person class
class Parson{
/ / the constructor
constructor(name,age){
this.name = name
this.age = age
}
// General method
speak(){
// Speak on the chain
console.log(I call `The ${this.name}This year, IThe ${this.age}At the age of `); }}// Create a student class that inherits parson
class Student extends Parson{
// No constructor is moved directly to the inherited constructor
}
const s1 = new Student("Zhang".12)
console.log(s1);
Copy the code
Use the constructor if there are new attributes after inheritance
// Create a Person class
class Parson{
/ / the constructor
constructor(name,age){
this.name = name
this.age = age
}
// General method
speak(){
// Speak on the chain
console.log(I call `The ${this.name}This year, IThe ${this.age}At the age of `); }}// Create a student class that inherits parson
class Student extends Parson{
constructor(name,age,grade){
super(name,age) // Super can only be written on the first line
this.grade = grade
}
}
const s1 = new Student("Zhang".12."Higher") // One grade more than Parson
console.log(s1);
Copy the code
The constructors in the class are not required to be written or the methods in the class are placed on the prototype object
The component class type
Classes must inherit React built-in classes must have render methods render must return values
// Create a class component
class MyComponent extends React.Component{ // Must inherit
render(){ / / render method
return <h2>I am a class-defined component (for definition of a complex component)</h2> / / the return value}}// Render the component to the page
ReactDOM.render(<MyComponent/>.document.getElementById('test'))
/* The render function in class MyComponent is used by instances but does not have a new instance. React automatically creates a new instance and calls the render method */
// Create a class component
class MyComponent extends React.Component{
render(){
// render where? -- On the prototype object of MyComponent for instance use
// Who is this in rander? --MyComponent instance object or component instance object
console.log(this);
return <h2>I am a class-defined component (for definition of a complex component)</h2>}}// Render the component to the page
ReactDOM.render(<MyComponent/>.document.getElementById('test'))
Copy the code
$state- The core property of the component instance – understanding state
Functional component = Simple component = No state Class component = Complex component = State
Fix this pointing problem in changeWeather
class Weather extends React.Component{
constructor(props){
super(props)
// Initialization state
this.state = {isHot:true}}render(){
// Read the state
const {isHot} = this.state
// We must write this.changeWeather because we can't get it directly
return <h1 onClick={this.changeWeather.bind(this)}>The weather is {isHot? Hot ":" cold "}</h1>
}
changeWeather(){
// This points to undefined if you don't say bind
console.log(this.state);
}
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code
Or this in the following constructor is the instance object
class Weather extends React.Component{
constructor(props){
super(props)
// Initialization state
this.state = {isHot:true}
this.changeWeather = this.changeWeather.bind(this) // This is the instance object in the constructor, and the output from this is its own changeWeather
}
render(){
// Read the state
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
}
changeWeather(){
console.log(this.state);
}
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code
The use of setState is similar to that of applets
I solved the pointing problem above and now I’m going to click on the transform true and false
class Weather extends React.Component{
constructor(props){
super(props)
// Initialization state
this.state = {isHot:true}
this.changeWeather = this.changeWeather.bind(this)}render(){
// Read the state
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
}
changeWeather(){
// This is true, but the page will not be hot and cold constantly switching
this.state.isHot = !this.state.isHot
console.log(this.state.isHot);
}
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code
Since things in the state cannot be changed directly, finding that property and changing it directly is a direct change
class Weather extends React.Component{
constructor(props){
super(props)
// Initialization state
this.state = {isHot:true}
this.changeWeather = this.changeWeather.bind(this)}render(){
// Read the state
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
}
changeWeather(){
// Seriously note that the state state cannot be changed directly
// this.state.isHot = ! This.state. isHot // Error
// console.log(this.state.isHot);
ChangeWeather = this.changeweather.bind (this)
// This is an instance of Weather
// The prototype of the instance object has render on it. The prototype of the changeWeather object is React.Com. Ponent has a method called setState
this.setState({
isHot:!this.state.isHot
})
}
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code
A small summary of the overall structure
A small summary
class Weather extends React.Component{
constructor(props){ // when the generated instance is called only once
super(props)
}
render(){} //1+n times to return the component and then to rerender when the event function first triggers the modification state
changeWeather(){} // Trigger several times execute several times
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
class Weather extends React.Component{
constructor(props){ // Why is the constructor written?
super(props)
// The state must be initialized
this.state = {
isHot:true.wind:"The wind"
}
// Solve this pointing problem
this.changeWeather = this.changeWeather.bind(this)}render(){ // Render this is the component instance object
// Read the state
const {isHot,wind} = this.state
/ / do show
return <h1 onClick={this.changeWeather}>The weather is {isHot? Hot ":" cold "}</h1>
}
changeWeather(){
this.setState({
isHot:!this.state.isHot // Get value update value
})
}
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code
To streamline the state
class Weather extends React.Component{
constructor(props){} // This must refer to the instance object
render(){} // React new calls render automatically, so this is also an instance object
changeWeather(){} // This is undefined internal automatic strict mode
}
constructorThere are only two things in therethisYou can write an assignment directly to the initialization state class but it must be deadclass Weather extends React.Component{
constructor(props){}
render(){}
changeWeather(){}
a = 1
}
newThe instance that comes out will have a= 01The property of is equivalent to that ofconstructorWrite the insidethis.a= 1, so it's straight downstate
class Weather extends React.Component{
constructor(props){}
state = {name:"xxx"}
render(){}
changeWeather(){}}Copy the code
Simplified Constructord’s this points to the problem
class Weather extends React.Component{
constructor(props){}
render(){}
changeWeather = function(){} A =1
// This method is used on the prototype so that it can be directly applied to the instance properties
// It's still not enough to just write it like this
}
class Weather extends React.Component{
constructor(props){}
render(){}
// The arrow will take the external this
log(this)?? // You can't write a function body inside a class, so don't worry about it
changeWeather = () = >{
console.log(this) // is an instance object of weather}}Copy the code
The final structure pays attention to key points
class Weather extends React.Component{
// Initialization state
state = {
isHot:true.wind:"Cold"
}
render(){
const {isHot,wind} = this.state
return <h1 onClick={this.changeWeather}>The weather is {isHot? },{wind}</h1>
}
// Custom methods -- assignment statement + arrow function
changeWeather = () = >{
this.setState({
isHot:!this.state.isHot
})
}
}
ReactDOM.render(<Weather/>.document.getElementById("test"))
Copy the code
Pay attention to the point
- Render’s this is the component instance object (react automatically new and calls).
- Component custom methods in which this is undefined (because the class is automatically in strict mode) and the event is called without this a. Force binding this through bind() (bind, unlike call, does not perform) b. Through the arrow function
- The state data cannot be changed directly. You must use setState in the React prototype
$props- The core property of the component instance – props
The basic use of simple values
// Create a component
class Parson extends React.Component{
state = { name:'tom'.age:18.sex:'woman' }
render(){
const {name,age,sex} = this.state
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>
)
}
}
ReactDOM.render(<Parson/>.document.getElementById('app1'))
ReactDOM.render(<Parson/>.document.getElementById('app2'))
ReactDOM.render(<Parson/>.document.getElementById('app3'))
Copy the code
This is the basic notation, but now I need external data to render the above notation as if it were my own thing and render three people with the same name, gender and age
// Create a component
class Parson extends React.Component{
render(){
console.log(this);
const {name,age,sex} = this.props
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>
)
}
}
ReactDOM.render(<Parson name='tom' age='18' sex='woman' />.document.getElementById('app1'))
// React automatically passes name: Tom to props
Copy the code
Batch pass props for example have a lot of information
Transferring label attributes in batches
// Create a component
class Parson extends React.Component {
render() {
console.log(this);
const { name, age, sex } = this.props
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>)}}const result = { name: "Liu".age: 18.sex: "Female" }
ReactDOM.render(<Parson name={result.name} age={result.age} sex={result.sex} />.document.getElementById('app1'))
//nonono cannot write this if there is too much data
/ / writes
ReactDOM.render(<Parson {. result} / >.document.getElementById('app2') Test...var a = {n: 1.b: 2.c: "Hello"}
var b = {say:"hello"}
varobj = {... b,... A} orvar obj = new Object({... b,... A}) obj = {say: "hello".n: 1.b: 2.c: "Hello"}
Copy the code
Limit propTypes for props
Restrictions must be written to the class, not the instance
// Create a component
class Parson extends React.Component {
render() {
console.log(this);
const { name, age, sex } = this.props
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>)}}React every time new asks Parson if it has this thing
Parson.propTypes = {
// Start with a capital P, which is a built-in property of React
name:React.propTypes.string // The type is also lowercase
}
const result = { name: "Liu".age: 18.sex: "Female" }
ReactDOM.render(<Parson name={result.name} age={result.age} sex={result.sex} />.document.getElementById('app1'))
ReactDOM.render(<Parson {. result} / >.document.getElementById('app2'))
Copy the code
Limit rules
Parson.propTypes = {
// Start with a capital P, which is a built-in property of React
name:React.propTypes.string // The type is also lowercase} But this is written in16.Xx after being abandoned Because the react with propTypes will change a lot And sometimes also don't have to restrict16.The PropTypes object is added directly to the class by loading prop-types.js to restrict component tags. PropTypes writeReact every time new asks Parson if it has this thing
Parson.propTypes = {
// Start with a capital P, which is a built-in property of React
name:PropTypes.string.isRequired, // The type is also lowercase and must be entered
sex:propTypes.string,
}
Copy the code
The default value
// Specify a default value
Parson.defaultProps = {
sex:"No, male, female.".age:18
}
Copy the code
If the method is worn, the restriction is Handel: proptypes.func
// Create a component
class Parson extends React.Component {
render() {
const { name, age, sex,handel } = this.props
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>)}}React every time new asks Parson if it has this thing
Parson.propTypes = {
// Start with a capital P, which is a built-in property of React
name:PropTypes.string.isRequired, // The type is also lowercase and must be entered
sex:PropTypes.string,
age:PropTypes.number,
handel:PropTypes.func / / method
}
// Specify a default value
Parson.defaultProps = {
sex:"No, male, female.".age:18,}function handle(){}
const result = { name: "Liu".sex:"Male".age: 18.handle:handle}
ReactDOM.render(<Parson {. result} / >.document.getElementById('app2'))
Copy the code
The abbreviation for propType props is read-only and cannot be changed
Props is read-only. This. Props is equal to XXX
render() {
const { name, age, sex,handel } = this.props
this.prop.xxx = xxx / / an error
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>)}Copy the code
shorthand
class Parson extends React.Component {
render() {
const { name } = this.props
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>)}static propTypes = { // The class must be static. // The class must be static
name: PropTypes.string.isRequired
}
static defaultProps = {
sex: "No, male, female."
}
}
Parson.propType = { // If you want to write this directly, add static
name: PropTypes. String. IsRequired,} class is equivalent to the prototype of instance, all the methods defined in the class, are examples of inheritance. If you have a method, plusstaticKeyword, indicating that the method is not inherited by the instance, but is called directly from the class, which is called a "static method."class Foo {
static say() {
return 'hello';
}
}
Foo.say() // 'hello'
var foo = new Foo();
foo.say() // TypeError: foo.classMethod is not a functionNote that if static methods containthisKeyword, thisthisClass, not instance.Copy the code
Constructors and props in class components
Before the React component is mounted, its constructor is called. When implementing a constructor for a react.componentsubclass, it should be called before any other statementsuper(props). Otherwise,thisThere may be undefined bugs in the.props constructor.constructor(props){
super(a)// If you don't pass it here
console.log(props);
console.log(this.props); // Then you can get undefined directly
}
Copy the code
Props for functional components
Functions can have props state because they can take parameters
function Parson(props) {
const { name, sex, age, } = props
return (
<ul>
<li>Name: {name}</li>
<li>Gender: {age}</li>
<li>Age: {sex}</li>
</ul>
)
}
Parson.propTypes = {
name: PropTypes.string.isRequired,
sex: PropTypes.string,
age: PropTypes.number,
handel: PropTypes.func
}
Parson.defaultProps = {
sex: "No, male, female.".age: 18,}function handle() {}const result = { name: "Liu".age: 18.handle: handle }
ReactDOM.render(<Parson {. result} / >.document.getElementById('app1'))
Copy the code
Props to summarize
// Do not change the props value to read-only inside the component
// You can use {... Obj} to batch pass
ReactDOM.render(<Parson {. result} / >.document.getElementById('app1'))
// limit the propsClass name. defaultProps = {sex: "No, male, female.".age: 18} or write it inside the class plusstatic
// Functional components can also use props
Copy the code
$refs- Core attributes and event handling for component instances
The string form ref- is no longer recommended and 16.8 still works
So the first thing we have to do is we have two input fields and the first one is to put something in and click on the button and the second one is to put something in and lose focus
//
class Parson extends React.Component {
render() {
return (
<div>// add id here<input id="i1" type="text" placeholder="Click the button to output data" />
<button onClick={this.btn}>Click on my popup left side data</button>
<input type="text" placeholder="Lost focus output data" />
</div>
)
}
btn = () = > {
const i = document.getElementById("i1") // React is used
alert(i.value)
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
// Use ref in react
class Parson extends React.Component {
render() {
return (
<div>/ / use the ref<input ref="input1" type="text" placeholder="Click the button to output data" />
<button onClick={this.btn1}>Click on my popup left side data</button>
<input ref="input2" onBlur={this.btn2} type="text" placeholder="Lost focus output data" />
</div>
)
}
btn1 = () = > {
console.log(this.refs.input1.value) // refs is used here
}
btn2 = () = > {
console.log(this.refs.input2.value)
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code
Small problem with the number of ref calls in callback form
Labels must use the ref keyword
class Parson extends React.Component {
render() {
return (
<div>// go to this and find render<input ref={c= >This. input1 = c} type=" placeholder "placeholder=" placeholder"<button onClick={this.btn1}>Click on my popup left side data</button>
<input ref={(c)= >{this.input2 = c}} onBlur={this.btn2} type="text" placeholder=" placeholder "/></div>
)
}
btn1 = () = > {
console.log(this.input1.value);
}
btn2 = () = > {
console.log(this.input2.value);
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code
The callback form directly writes the callback function this to recder to the instance
Minor problem with the number of calls the number of calls to the callback function when written as a callback function and the state has been changed React will call render again and the callback will reset to null before assigning to the function you wrote
When the code is as follows
class Parson extends React.Component {
state = {
isHot: true
}
render() {
const { isHot } = this
return (
<div>
<input ref={c= >{ this.input1 = c; Console. log(" output ", c); }} type="text" /><button onClick={this.btn1}>Click on my popup left side data</button>
<h1 onClick={this.handleH1}>Weather {isHot? "Very hot" : "cold "}</h1>
</div>
)
}
btn1 = () = > {
console.log(this.input1.value);
}
handleH1 = () = > {
this.setState({
isHot:!this.isHot
});
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code
Log will output a output when the page is generated because React executes render once by default
When the and label is clicked, the output is as follows: null is printed because the reder is initialized to NULL when running the function when the state changes
The binding functions in a class that the solution mounts to its own functions can be avoided but in most cases irrelevant
class Parson extends React.Component {
state = {
isHot: true
}
render() {
const { isHot } = this
return (
<div>
<input ref={this.saveInput} type="text" />
<button onClick={this.btn1}>Click on my popup left side data</button>
<h1 onClick={this.handleH1}>{this.state.ishot? "Very hot" : "cold "}</h1>
</div>
)
}
saveInput = (c) = >{
this.input1 = c
console.log("Output",c);
}
btn1 = () = > {
console.log(this.input1.value);
}
handleH1 = () = > {
this.setState({
isHot:!this.state.isHot
});
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code
The use of createRef
class Parson extends React.Component {
myRef1 = React.createRef() // Returns a container that stores the nodes identified by ref
// is equal to I made a container hanging on the instance itself named myRef
// Only one container can be stored in the container
myRef2 = React.createRef()
state = {
isHot: true
}
render() {
const { isHot } = this
return (
<div>
<input ref={this.myRef1} type="text" />{/* React.createRef() creates a container and stores the current node in the container */}<input ref={this.myRef2} onBlur={this.handle2} type="text" />
<button onClick={this.handle1}>Click on my popup left side data</button>
</div>
)
}
handle1 = () = > {
console.log(this.myRef1.current); // React generates current for you
}
handle2 = () = > {
console.log(this.myRef2.current);
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code
Example 2
class Parson extends React.Component {
myRef = {
myRef1:React.createRef(),
myRef2:React.createRef()
}
state = {
isHot: true
}
render() {
const { isHot } = this.state
// Try the structure here and it doesn't work
// One at a time
const {myRef1,myRef2} = this.myRef
return (
<div>
<input ref={myRef1} type="text" />{/* React.createRef() creates a container and stores the current node in the container */}<input ref={myRef2} onBlur={this.handle2} type="text" />
<button onClick={this.handle1}>Click on my popup left side data</button>
</div>
)
}
handle1 = () = > {
console.log(this.myRef.myRef1.current); // React generates current for you
}
handle2 = () = > {
console.log(this.myRef.myRef2.current);
}
}
ReactDOM.render(<Parson />.document.getElementById('app1'))
Copy the code
Event handling can be done with target instead of refs
- Use the onXxx property to specify event handlers (case sensitive). Instead of using the element DOM events – encapsulated for better compatibility, events in B. React are handled by event delegates (delegated to the outermost element of the component) – for efficiency
- Get the DOM element object where the event occurred via event.target
Collect form data
Controlled uncontrolled components
The managed component uses the DOM of the fetch input class as your input is maintained into the state and fetched directly from the state when needed
class Login extends React.Component {
state = {
username:' '.password:' '
}
render() {
return (
<div>
<form action="" onSubmit={this.handleSubmit}>The user name<input onChange={this.saveUsername} type="text" name="username" />password<input onChange={this.savePassword} type="password" name="password" />
<button>landing</button>
</form>
</div>
)
}
saveUsername = (e) = > {
this.setState({
username:e.target.value
})
}
savePassword = (e) = > {
this.setState({
password:e.target.value
})
}
handleSubmit = (e) = > {
// Print the address of the action that will be forwarded to the form
e.preventDefault() // Block the default event to block form submission
const {username,password} = this.state
console.log(username,password);
}
}
ReactDOM.render(<Login />.document.getElementById('app1'))
Copy the code
Uncontrolled use of ref to get the current value of the node
A lot of them are written using currization
If I wanted to log in, I could write it like this
class Login extends React.Component {
state = {
username:' '.password:' '
}
render() {
return (
<div>
<form action="" onSubmit={this.handleSubmit}>The user name<input onChange={this.saveUsername} type="text" name="username" />password<input onChange={this.savePassword} type="password" name="password" />
<button>landing</button>
</form>
</div>
)
}
saveUsername = (e) = > {
this.setState({
username:e.target.value
})
}
savePassword = (e) = > {
this.setState({
password:e.target.value
})
}
handleSubmit = (e) = > {
e.preventDefault() // Block the default event to block form submission
const {username,password} = this.state
console.log(username,password);
}
}
ReactDOM.render(<Login />.document.getElementById('app1'))
Copy the code
But if I’m going to register my phone and I have a lot of information that’s just too bloated to write
The first method is passed in when the event is triggeredclass Login extends React.Component {
state = {
username: ' '.password: ' '
}
render() {
return (
<div>
<form action="" onSubmit={this.handleSubmit}>The user name<input onChange={(e)= >This.saveformdata ('username',e)} type="text" name="username" /> Password<input onChange={(e)= >this.saveFormData('password',e)} type="password" name="password" />
<button>landing</button>
</form>
</div>)}// Save the form data to state
saveFormData = (v,e) = > {
console.log(v,e.target.value);
this.setState({
[v]:e.target.value // Add [] or else you won't read variable data as a 'v' string
})
}
}
ReactDOM.render(<Login />.document.getElementById('app1') -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --// The second one starts with the pass in username function
class Login extends React.Component {
state = {
username: ' '.password: ' '
}
render() {
return (
<div>
<form action="" onSubmit={this.handleSubmit}>// select * from user where username = 'username'<input onChange={this.saveFormData('username')} type="text" name="username" />password<input onChange={this.saveFormData('password')} type="password" name="password" />
<button>landing</button>
</form>
</div>)}// When the event is raised in return
saveFormData = (v) = > {
//console.log(v);
return (e) = > {
console.log(v,e.target.value);
this.setState({
[v]:e.target.value
})
}
}
}
ReactDOM.render(<Login />.document.getElementById('app1'))
Copy the code
Component life cycle
The basic use
Basic componentDidMount componentWillUnmount unload components ReactDOM. UnmountComponentAtNode (document. GetElementById (‘ app1))
class Life extends React.Component {
/ / state
state = {
opacity: 1
}
// State update during initialization
render() {
const { opacity } = this.state
return (
<div>
<h2 style={{ opacity: opacity}} >What if you can't React?</h2>
<button onClick={this.death}>No way!</button>
</div>)}// The lifecycle component does not need to be called when it is mounted because it is not used as a callback
// The component is mounted
componentDidMount() {
this.timer = setInterval(() = > {
let { opacity } = this.state
opacity += 1
if (opacity <= 0) opacity = 1
this.setState({
opacity
})
}, 200);
}
// The component will be uninstalled
componentWillUnmount() {
clearTimeout(this.timer)
}
death = () = > {
// You can also turn off the timer here
// Uninstall the component
ReactDOM.unmountComponentAtNode(document.getElementById('app1'))}}// Render to page mount to page mount unmount
ReactDOM.render(<Life />.document.getElementById('app1'))
Copy the code
Order of components
Constructor componentWillMount components will mount render componentDidMount components mounted Using ReactDOM. UnmountComponentAtNode () will adjust this function before unloading ComponentWillUnmount The component is about to be unmountedCopy the code
When setState() is called
ShouldComponentUpdate () Specifies the hook to be updated. Shouldcomponentwillupdate render Specifies the hook to be updated componentDidUpdateCopy the code
When forceUpdate() is called to force an update
There’s a valve less than the update and you don’t want to make any changes to the state like let you update and just use this
Component to be updated hook componentWillUpdate Render component updated hook componentDidUpdateCopy the code
Summary of the code
// Create a component
class Life extends React.Component {
/ / the constructor
constructor(props) {
super(props)
console.log('Life-constructor');
// Initialization state
this.state = {
count: 0}}render() {
console.log('Life-render');
const {
count
} = this.state
return (
<div>
<h2>The current sum is {count}</h2>
<button onClick={this.add}>Gal.</button>
<button onClick={this.force}>Forced to update</button>
</div>)}// The component will be mounted
componentWillMount() {
console.log('Life-componentWillMount');
}
// The component is mounted
componentDidMount() {
console.log('Life-componentDidMount');
}
//------------------------------------------------------------------------------
// When setState calls return true by default, false does not go down
// The props and state to be changed next
shouldComponentUpdate(nextProps,nextState) {
console.log('Life-shouldComponentUpdate');
return true
}
// The hook that the component will update
componentWillUpdate() {
console.log('Life-componentWillUpdate');
}
// The component's updated hook
componentDidUpdate() {
console.log('Life-componentDidUpdate');
}
//------------------------------------------------------------------------------
// Before uninstallation
componentWillUnmount() {
console.log('Life-componentWillUnmount');
}
add = () = > {
let { count } = this.state
this.setState({
count: count + 1
})
}
force = () = > {
this.forceUpdate()
}
}
// Render component
ReactDOM.render(<Life />.document.getElementById('app1'))
Copy the code
Parent component Render process
First paste the code A component name to B component display
class A extends React.Component {
state = {
carName: 'Mercedes' //A components are defined and not displayed
}
render() {
return (
<div>
<div>A</div>{/* Cars in A state are not displayed */}<button onClick={this.changeCar}>To change</button>
<B {. this.state} / >
</div>
)
}
changeCar = () = > {
this.setState({
carName: 'otto'}}})class B extends React.Component {
componentWillReceiveProps(props){
console.log('child components will accept the label attribute (parameters) componentWillReceiveProps',props);
}
render() {
console.log(this.props);
return (
<div>
<div>B</div>
<div>{this.props.carName}</div>{/* The car passed by A is displayed in the B component */}</div>)}}// Render component
ReactDOM.render(<A />.document.getElementById('app1'))
Copy the code
The life cycle
Once the render of the parent component executes, The child component will execute component will accept the label attribute (parameters) componentWillReceiveProps (props) but you will find that the parent component of props for the first time coming (when is page rendering) for the first time will not call again the props value of the parent component ShouldComponentUpdate () returns the valve by defaulttrueComponentWillUpdate hook componentDidUpdate(preProps,preState)Copy the code
New release lifecycle
Hooks to be deprecated in the new version
The following three front to add UNSAFE_ componentWillMount componentWillUpdate componentWillReceiveProps (props) but will be abandoned Don't use these three so it's best to the new versionCopy the code
The new usage scenarios are extremely rare, so the most common ones are only three DidMount DidUpdate WillUnmount
New version of hook usage
Static getDerivedStateFromProps(props, State){// Return a state object or null // If a state object is returned, the component state is equal to the object value and the value cannot be modified // If the value of state is dependent on props at any time, then you can use, Return null return {props} return {name:" hello "}} // But this component makes the code difficult to maintain, etc. So use scenarios are extremely rare. This function does something before updating GetSnapshotBeforeUpdate (){return Snapshot value Return value is passed to componentDidUpdate(preProps,preState,v) with the third argument}Copy the code
React application (via scaffolding)
The basic use
- Install NPM i-g create-react-app
- Go to the directory where you want to create the project and run create-react-app hello-react
- Enter the CD hello – react
- Start the project NPM start yarn start Enable the developer server without yarn installed NPM start yarn Build Generate the final static file yarn eject Expose all webPack configuration files (this operation is irreversible)
File to read
Json Application shell configuration Robots. TXT crawler rule file SRC app.css app.js app.test. js Test file index.js entry file Setuptests.js component testCopy the code
index.html
<html lang="en">
<head>
<meta charset="utf-8" />
<! -- %PUBLIC_URL% represents the path of the public folder -->
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<! -- Enable ideal viewport mobile adaptation -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<! -- Configure the color of the browser TAB + address bar (only supports Android mobile browsers and not very compatible) -->
<meta name="theme-color" content="# 000000" />
<! -- Search Engine Optimization -->
<meta
name="description"
content="Web site created using create-react-app"
/>
<! -- Apple Browser logo added to the home page -->
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<! -- Configuration related to application shell -->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<! -- If the browser does not support the execution of javascript script -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<! -- -- -- > container
<div id="root"></div>
</body>
</html>
Copy the code
Index. Js interpretation
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App'; / / component
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>// There will be an error when adding this component<App />
</React.StrictMode>.document.getElementById('root')); reportWebVitals();// Record page performance
Copy the code
Conflict styles
You can use modularity
Hello.js hello.css Rename hello.css to hello.module. CSS and import import hello from './hello.module. CSS '<div in hello.js className={hello. Your style name}></div>Copy the code
You can also write styles using less
hello{
.balbala{
}
}
Copy the code
Plug-in installation tips
Install vs plugin ES7 React/story/GraphQL/React – Native snippets initialization RCC directly
Small case – Composite use of components
Input box list select all delete regions
A component list. Each item in the component list is a component. The delete field is a component
Child components pass values to parent components
The parent component binds a function to the child component propertyexport default class Father extends Component{
render(){
return(
<div>
<Son handle={this.handle} />
</div>
)
}
handle = (data) = >The {log(data)}} child component is called directlythis.props. Hanlde (Pass the value to the parent component to get it)Copy the code
The plug-in generates a unique key
The plug-in name nanoid is smaller than the UUID NPM I Nanoid is introduced when used
import {nanoid} from 'nanoid'
log(nanoid())
Copy the code
TodoList case summary
- Split components, implement static components, note the className, style notation
- Dynamic initialization list, how to determine which component to put data in state? — Used by a component: placed in its own state — used by a component: placed in their parent component’s state (officially called: state promotion)
- Parent component communication — the parent component passes to the child component via props — the child component passes to the parent component via props, but the parent component passes functions to the child component in advance
- Note the difference between defaultCheckd and value
- Where is the state? Where is the way to manipulate the state
React Ajax sends requests
A quick review of Axios and Node
node
const { response } = require('express');
const express = require('express')
const app = express()
app.use((request,response,next) = >{
console.log('Someone has requested server 1');
next()
})
app.get('/students'.(request,response) = >{
const students = [
{id:'001'.name:'tom'.age:18},
{id:'002'.name:'jerry'.age:19},
{id:'003'.name:'tony'.age:20},
]
response.send(students)
})
app.listen(5000.(err) = >{
if(! err){console.log('Successful startup can request student data! ');}
})
Copy the code
axios
The first one, BTN is equal toasync() = > {const result = await axios.get('http://localhost:5000/students')
.catch((err) = > {console.log(err); $axios.get();'http://localhost:5000/students')
.then((response) = >{},(err) = >{}). Then the first of the two functions succeedsCopy the code
The react cross-domain
Proxy cross domain you 3000 send 5000 can but when the data back will be ajax interception, proxy without Ajax blocking your own 3000 port —– proxy port 3000 —– server 5000
Receive mobile phone you look for the teacher he does not give you, you look for parents to look for the teacher to take a mobile phone, parents are giving you the parent is the agent, you are the current address, the teacher is the request address
Suppose you are3000The teacher is5000
1.Add a sentence to package.json"proxy":"http://localhost:5000" // Address + port
2.Restart the project3.Make a request to your own portCopy the code
If you want to send a request to multiple addresses such as 5001, the scaffolding will open 3000 for you, and you request 3000/index.html. If you want to send a request to multiple addresses such as 5001, the scaffolding will open 3000 for you
Delete the previous package.json"proxy":"http://localhost:5000 "add a new file to SRC: setupproxy.js // introduce a built-in module that is available when react is initialized to const proxy = Require ('http-proxy-middleware') module.exports = function(app) {app.use(proxy('/api1',{// meet /api1), Target :'http://localhost:5000', // to whom the request is forwarded changeOrigin:true, // default is false, Request. Get ('Host') = 5000 If false: 3000 pathRewrite:{'^/ API1 ':'}} proxy('/api2',{ target:'http://localhost:5001', changeOrigin:true, PathRewrite: {' ^ / api2 ':'} / / detect api2 went 5001}})) send request with api1 or 2 will automatically convert $axios. Get (' http://localhost:3000/api1/students') $axios.get('http://localhost:3000/api2/cars')Copy the code
React Cross-domain approach summary
Methods a
Add the following configuration to package.json
"proxy":"http://localhost:5000"
Copy the code
Description:
- Advantages: Simple configuration and no prefix can be added when the front-end requests resources.
- Disadvantages: You cannot configure multiple agents.
- How it works: Configure the proxy so that when 3000 resources are requested that do not exist, the request is forwarded to 5000 (matching front-end resources is preferred).
Method 2
- Step 1: Create the proxy profile
Create a configuration file under SRC: SRC/setupproxy.jsCopy the code
- Write setupproxy.js to configure specific proxy rules:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(
proxy('/api1', { // API1 is the request that needs to be forwarded (all requests with/API1 prefix are forwarded to 5000)
target: 'http://localhost:5000'.// Configure the forwarding target address (the server address that can return data)
changeOrigin: true.// Controls the value of the host field in the request header received by the server
/* When changeOrigin is set to true, the host in the request header received by the server is: localhost:5000 The default changeOrigin value is false, but we usually set the changeOrigin value to true */
pathRewrite: {'^/api1': ' '} // Remove the request prefix to ensure that the backend server is normal request address (must be configured)
}),
proxy('/api2', {
target: 'http://localhost:5001'.changeOrigin: true.pathRewrite: {'^/api2': ' '}}}))Copy the code
Description:
- Advantages: Multiple proxies can be configured to flexibly control whether requests go through proxies.
- Disadvantages: Cumbersome configuration and prefix must be added when the front-end requests resources.
Small case study – Github search
JSX can only write expressions such as ternary and not statements such as if
So when I write the method I'm going to define in the parent component of my App what I'm going to get for my parameters and I'm going to get this many things from the search component state = {users: [].// List of users
isFirst: true.// Whether to open the page for the first time
isLoading: false.// The request is waiting
err: ' '.// Store request error information} do I need to write so many methods to put in? This directly// Update app status
updateAppState = (stateObj) = > {
this.setState(stateObj)} setState is written to return an object directlyCopy the code
JSX can only write expressions such as ternary and not statements such as if
Only expression ternary checkerings can be written to determinerender() {
const { users,isFirst,isLoading,err } = this.props
return (
<div className="row">
{
isFirst ? <h2>Is this your first use? Welcome to use</h2> :
isLoading ? <h2>Is the data request completed? Loading.....................</h2> :
err ? <h2>Is there an error?<h2/> :
users.map((userItem, i, arr) => {
return <Item userItem={userItem} key={userItem.id} />})}</div>)}Copy the code
The error object is saved when the request comes back
axios.get(`https://api.github.com/search/users1`, {
params: { q: value }
}).then((result) = > {
this.props.updateAppState({
isLoading: false.users: result.data.items
})
},(err) = > {
console.log(typeof err);
this.props.updateAppState({
isLoading: false.err:err / /!!!!!!!!!!!!!! That's not going to work because it's an object and it's not going to render and it's going to store err's message
err:err.message
})
})
Copy the code
Any component pass-message subscription-publish mechanism
PubSubJS
Download the package NPM I pubsub-js or YARN Add Pubsub-js Subscribe messages Subscribe messages to whoever receives messagesvar mySubscriber = function(msg,data){
log(msg,data)
}
var token = PubSub.subscribe('MY TOPIC',mySubscriber) / / subscribeorvar token = PubSub.subscribe('getMainValue'.(msg, data) = >{
console.log('data',data);
})
PubSub.unsubscribe(token) // Clear the subscription· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·// Components subscribe as soon as they are placed on the page, so put them in componentDidMount instead of Update
PubSub.publish('MY TOPIC'.'hello word! 'The helloWord here will be passed to the data aboveCopy the code
Token writes to this as follows:
// Subscribe as soon as the component is placed on the page
componentDidMount() {
this.token = PubSub.subscribe('getMainValue'.(msg, data) = > {
this.setState(data)
})
}
/ / unloading
componentWillUnmount(){
PubSub.unsubscribe(this.token)
}
Copy the code
Fetch sends a request
How many ways are there to send a request?
- XMLHttpRequest on XHR //window
- JQuery // Inferior callback hell
- Axios // Promise style no callback hell
The front-end JQ and AXIos are both wrapped XHR and the back-end HTTP JQ wrapped by AXIos. Axios is both a third-party library, and the fetch on window is not a third-party library and it is also promise style
Basic usage comparison
// The data in the input box can be searched for github users by following the link below
const { inputRef: { value } } = this
axios.get(`https://api.github.com/search/users`, {
params: { q: value }
}).then(
result= > {},
err= >{}) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --const { inputRef: { value } } = this
/ / short
fetch(`https://api.github.com/search/users?q=${value}`).then(
res= > {
return res.json() // The data must be in then to get
},
err= > {
return new Promise(() = >{})
}
).then(
res= > {
console.log('Obtain success', res);
},
err= > {
console.log('Fetch failed', err.message); })// abbreviation unified handling error
fetch(`https://api.github.com/search/users?q=${value}`).then(
res= > res.json()
).then(
res= > { console.log('Data obtained successfully', res) }
).catch( // Handle errors uniformly
err= > {console.log(err.message)}
)
// async await
try{
const response = await fetch(`https://api.github.com/search/users?q=${value}`)
const data = await response.json() //await can only be followed by promise, but response.json() is really a promise
console.log(data)
}catch(err){ //await does not catch errors so catch them here
console.log(err.message)
}
// Focus on separation
fetch(`https://api.github.com/search/users?q=${value}`).then(
// It is only used to check whether the connection can be made even if 404 succeeds
res= > {
// console.log(' Server contacted successfully, but no data ', res);
Json () returns a promise in res.json()
// console.log('res.json()',res.json());
// Direct then() is too messy so return returns in then
return res.json() Res.json () returns a promise
},
404 will not go because 404 means there is no resource but it is connected
err= > {
console.log('Failed to contact server', err);
// Return promise, then executes. Return non-promise, success and output
// So if you don't write return, it will return underined by default
// Return an initialized promise instance and no further progress will be made
return new Promise(() = >{})
}
).then( // the previous res.json() returns a promise, so then is caught
res= > {
// console.log(' succeeded ', res);
},
err= > {
// console.log(' failed to get ', err.message);})Copy the code
The React routing
An understanding of routing
A route is a mapping. Key :value For example, /home is not a link path
- Router. get(path,(request,response) => {}) When node receives a request, it finds a matching route based on the request path. Call functions in the route to process the request and return response data
- The value of the browser is component, which displays the content of the page. When the path of the browser changes to /home, The current routing component will become the Test component in two modes: one is history mode introduced by H5 BrowserRouter, a monitoring hash(anchor point) value change event HashRouter
React -router-dom Navlink is used
React router is a plugin library for React. This library is used to implement a SPA application in most react based projects, but cannot be introduced directly. There are three uses for this library: Web React-router-dom native Any There are two modes BrowserRouter/HashRouterimport { BrowserRouter, Link, Route } from 'react-router-dom';
// Outside
is an error
// Write routing links
<BrowserRouter>// Route link //to better write it in lower case<Link to="/about">About</Link>
<Link to="/home">Home</Link>
</BrowserRouter>
// Outside
is an error
// Register the route
<BrowserRouter>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
</BrowserRouter>
// Enclosing
is incorrect because a
tag is only one
// If you write two, they are independent and not together
// So the entire
tag is wrapped around the route link and the registered route
So you don't need to import BrowserRouter in the component. You just need Link and Route to put <BrowserRouter> in the index.js main file.<BrowserRouter><App /></BrowserRouter>.document.getElementById('root'));
Copy the code
In summary, route links automatically append styles
2. Change the Link in the navigation area to Link <Link to="/ XXXX "> XXXX </Link> 3. Match write paths in the function pane <Route path="/ XXXX "Component ={XXXX} /> 4. The outermost part of the main <App/> file wraps either <BrowserRouter> or <HashRouter> 5. If you want to style it instead of using Link use Navlink by default append the active style when clicked or use the activeClassName property to define < Navlink activeClassName="active" to="/about">About</NavLink>Copy the code
Routing components and common components
- Location Different General components in Component Routing components in the Pages folder
The basic component does not pass data to it. Then its Props does not pass data to it. The routing component takes three fixed parameters
ƒ go(n) goBack: ƒ goBack() goForward: ƒ goForward() push: ƒ push(path, state) replace: ƒ replace(path, state) history: pathname: "/about" search: "state: undefined history: params: {} path: "/about" url: "/about"Copy the code
Wrap route link Navlink tag body content is a special tag attribute children
<NavLink activeClassName="active" className="item" to="/about">About</NavLink>
<NavLink activeClassName="active" className="item" to="/about">About</NavLink>There are too many redundant things to write activeClassName="active" className="item"So encapsulate your own component <MyNavLink to="/home"> just write to <MyNavLink/>Copy the code
So the encapsulation
import React, { Component } from 'react'
import {NavLink} from 'react-router-dom'
export default class MyNavLink extends Component {
render() {
return (
<NavLink activeClassName="active" className="list-group-item" {. this.props} >
{/*this.props.children*/}
</NavLink>}} To write routing links elsewhere just <MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/Home">Home</MyNavLink>The value in the tag is also passed as an attribute to the component's props with the key childrenCopy the code
Routing Swich
- There is usually a one-to-one correspondence between Path and Component
- Switch improves route matching efficiency (Single match)
<div>
<MyNavLink to='/home' children='home' />
<MyNavLink to='/about' children='about' />
<MyNavLink to='/test' children='test' />
<Route path='/home' component={Home} />
<Route path='/about' component={About} />
<Route path='/about' component={Test} />// Both routes will be rendered because finding /about will look down // so importing the Switch tag from the route will not look down the route</div>
import { Route,Switch } from 'react-router-dom';
<Switch>
<Route path='/home' component={Home} />
<Route path='/about' component={About} />
<Route path='/about' component={Test} />
</Switch>
Copy the code
Style loss problem
The scaffolding startup will use webpack’s devServer to open a local url that points to the public folder and by default takes index.html and if you modify it to point to a path that doesn’t exist it will return index.html by default
When the route is multilevel and introduces a resource in public it will be lost if you refresh the page and add your first level path to the resource path because if you modify it to point to a path that doesn't exist then it will return index.html <MyNavLink to= by default'/first/home' children='home' />
<MyNavLink to='/first/about' children='about' />
<Route path='/first/home' component={Home} />
<Route path='/first/about' component={About} />If it is multi-level /first/home and the main file index. HTML introduces CSS in public <link rel="stylesheet" href="./bootstrap.css"> page refresh, request will take the /first pathCopy the code
The solution
The first way/ / remove the point logic as localhost: 3000 / bootstrap CSS
// instead of the current path of./
<link rel="stylesheet" href="/bootstrap.css"> the second// The absolute path of public only applies to react scaffolding
<link rel="stylesheet" href="%PUBLIC_URL%/bootstrap.css"> 3 uses hash routingCopy the code
Fuzzy matching and strict pattern
In general, do not enable strict matching unless the route hop is not correct. If this function is enabled, level-2 routes cannot be matched
<MyNavLink to='/home' children='home' />
<Route path='/a/b/home' component={Home} /><MyNavLink to='/a/home' children='home' />
<Route path='/home' component={Home} />Matched on fuzzy match <MyNavLink to='/home/a/b' children='home' />
<Route path='/home' component={Home} />
// Exact ={true} indicates that exact matching must be the same when registering routes
<MyNavLink to='/home' children='home' />
<Route exact path='/a/b/home' component={Home} />
<Route exact={true} path='/a/b/home' component={Home} />
Copy the code
Route Redirect
It is written at the bottom of all route registrations. When all routes fail to match, the route specified by the Redirect is redirected
<div>
<MyNavLink to='/home' children='home' />
<MyNavLink to='/about' children='about' />
<Switch>
<Route path='/home' component={Home} />
<Route path='/about' component={About} />
<Redirect to='/about' />
</Switch>
</div>If you can't match the Redirect, turn to the RedirectCopy the code
Embedded routines by
When registering child routes, set the path value of the parent route. Routes are matched in the order of registering routes. Routes are first matched in the parent component
Home News Message Home<div>
<MyNavLink to='/Home/News'>News</MyNavLink>
<MyNavLink to='/Home/Message'>Message</MyNavLink>
</div>
<div className='two'>
<Route path='/Home/News' component={News}></Route>
<Route path='/Home/Message' component={Message}></Route>
<Redirect to='/Home/News'></Redirect>
</div>
Copy the code
The routing component passes the Params parameter
Routing links (with parameters)<Link to={` /home/message/detail/ parameters1/ parameters2} >Register route (declare receiving)<Route path='/home/message/detail/: key of parameter 1 /: key of parameter 2 ' component={xxx}></Route>Accept the parameter this.props. Match.paramsCopy the code
code
export default class Message extends Component {
state = {
MessageList: [{id: '01'.title: News' 1 ' },
{ id: '02'.title: News' 2 ' },
{ id: '03'.title: 'the message 3']}},render() {
return (
<div>
{
this.state.MessageList.map((v, i, arr) => {
return (
<li key={v.id}>{/* Pass the params parameter to the routing component. Here we have to package a {} because the template string is something in JS.<Link to={` /home/message/detail/ ${v.id} / ${v.title} `} >{v.title}</Link>
</li>)})}<hr />{/* Declare the key that accepts the params argument */}<Route path='/home/message/detail/:id/:title' component={Detail}></Route>
</div>)}} subcomponent path='/home/message/detail/:id/:title'The acceptance parameters are in propsconst DetailData = [
{ id: '01'.content: 'China' },
{ id: '02'.content: 'hello' },
{ id: '03'.content: 'his'},]export default class Detail extends Component {
render() {
const { id,title } = this.props.match.params // This accepts the params parameter
const {content} = DetailData.find((v) = > {
return v.id === id
})
return (
<ul>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>)}}Copy the code
The routing component passes the search parameter
Routing links (with parameters)<Link to={` /home/message/detail/?id=${v.id}&title=${v.title}`} >{v.title}</Link>Registered routing (statement receiving) without receiving receive parameters. This props. The location. The search can get such a urlencoded code? Id =01&title= message 1 React automatically helps you download a library named queryString short QS two methods qs.parse(XXX) qs.stringify(XXX) so receive arguments are // because there will be a question mark so sclice truncates the first qs.parse(this.props.location.search.slice(1));Copy the code
The routing component passes the state parameter regardless of the state
Refreshing can also preserve parameters
Routing links (with parameters) are written as objects<Link to={{ pathname: '/home/message/detail', state: { id: v.id.title: v.title } }}>{v.title}</Link>Registered routing (statement receiving) do not need to register to receive normal component receives parameter = this. Props. The location. The state | | is undefinedCopy the code
Push pattern and replace pattern
One to replace one to push
The routing records are placed one by one in the innermost replace mode to replace the top of the two open modes <Link replace to='/xxxx'></Link>
<Link replace={true} to='/xxxx'></Link>
Copy the code
Programmatic routing navigation
The base component doesn’t give it any data so its props doesn’t have anything and the routing component takes three fixed arguments history Location match and in history there are two methods push and replace
Params <button onClick={() = > this.pushshow (v.id, v.tate)}>push </button><button onClick={()= >Enclosing replaceShow (v.i d, v.t itle)} > replace view</button>
pushShow = (id, title) = > {
/ / params parameters
this.props.history.push(`/home/message/detail/${id}/${title}`)
/ / search parameters
this.props.history.push(`/home/message/detail? id=${id}&title=${title}`)
/ / state parameters
this.props.history.push(`/home/message/detail`, {id:id,title:title})
}
replaceShow = (id, title) = > {
this.props.history.replace(`/home/message/detail/${id}/${title}`)}Copy the code
History also has a way of going forward and backward
<button onClick={this. The back} > back < / button ><button onClick={this.forward}>forward</button>
back = (params) = > {
this.props.history.goBack()
}
forward = (params) = > {
this.props.history.goForward()
}
forward = (params) = > {
this.props.history.go(2) // go back
}
Copy the code
withRouter
General components do not have apis on history and are processed into routing components using withRouter
import {withRouter } from 'react-router-dom';
class App extends Component {
render() {
return (
<div>
<button onClick={this.back}>The fallback</button>
</div>
)
}
back = (params) = > {
this.props.history.goBack()
}
}
export default withRouter(App) // Process returns a new component for the routing component
Copy the code
History is different from hash
- BrowserRouter uses the H5 History API. Hash Routers that are incompatible with IE9 and below use URL hashes
- Addresses in hash mode have #
- The state of the BrowserRouter is not lost after the page is refreshed, because the hash loses state if it is in the history object
Project package run
Injection.injection.js: $injection.injection.js: $injection.injection.js: $injection.injection.js: $injection.injection.js: $injection.injection.js Check to see if you are using BrowserRouter (the same as Vue's history mode) and need the backend configuration support, otherwise use HashRouter (with #). ------------------------------- or use a library serve NPM I serve -g and then directly serve in the path. If you want to go to the current a folder, you can directly CD there or you can serve a serve./aCopy the code
Expand the knowledge
SetState’s callback function is similar to nextTick()
Object type
// The callback is called after the status update and after the render update
this.setState( {} , callback )
export default class About extends Component {
render() {
return (
<div>
<h3>I'm About</h3>
<h1>The current sum is {this.state.count}</h1>
<button onClick={this.add}>I + 1 point</button>
</div>
)
}
state = {
count: 0
}
add = () = > {
const { count } = this.state
this.setState({ // an asynchronous thread will be opened to help you change
count:count+1
},() = > { // The callback is called after the status update and after the render update
console.log('callback'.this.state);
})
console.log('normal'.this.state); // React is an asynchronous thread}} Normal output after clicking button {count: 0{of} callbackcount: 1}
Copy the code
functional
this.setState( (state,props) = >{ return } , callback )
this.setState((state,props) = > {
return {count:state.count+1}},() = > {
// The callback function
})
this.setState((state,props) = > ({count:state.count+1}) , [callback] )
Copy the code
Objects are just syntactic sugar for functions
Suspense lazyload
// Introduce the lazy function
import React, { Component, lazy } from 'react';
import { Route, Switch, withRouter } from 'react-router-dom';
//lazy wraps the import component
const Home = lazy(() = > import('./pages/Home'))
const About = lazy(() = > import('./pages/About'))
class App extends Component {
render() {
return (
<div>
<MyNavLink to='/home' children='home page'></MyNavLink>
<MyNavLink to='/about'>The about page</MyNavLink>
<Switch>
<Route path='/home' component={Home}></Route>
<Route path='/about' component={About}></Route>
</Switch>
</div>)}}export defaultWithRouter (App) does this because it will wait forever if the connection is slow. You must set up a component for load time Suspense/ / into the Suspense
import React, { Component, lazy ,Suspense } from 'react';
Suspense tags wrap routing placeholders
The Suspense tag's fallback attribute is a wait-time component and cannot be lazily loaded
<Suspense fallback={<h1>Loading</h1>} ><Switch>
<Route path='/home' component={Home}></Route>
<Route path='/about/:abcdd' component={About}></Route>
</Switch>
</Suspense>
/ / for finally
const Home = lazy(() = > import('./pages/Home'))
const About = lazy(() = > import('./pages/About'))
class App extends Component {
render() {
return (
<div>
<NavLink to='/home'>The home page</NavLink>
<NavLink to='/about'>The about page</NavLink>
<Suspense fallback={<h1>Loading</h1>} ><Switch>
<Route path='/home' component={Home}></Route>
<Route path='/about' component={About}></Route>
</Switch>
</Suspense>
</div>)}}Copy the code
Hooks
New features/syntax in Act 16.8 let you use state and other React features in function components
First look at the differencesimport React from 'react'
/ / function type
function Fun1() {
function btn(){
console.log('btn');
}
return (
<div>
<h1>Digital {}</h1>Cannot be used without state<button onClick={btn}>I + 1 point</button>
</div>)}// Class components
class Fun2 extends React.Component {
render() {
return (
<div>
<h1>Digital {this. State. Num}</h1>
<button onClick={this.btn}>I + 1 point</button>
</div>
)
}
state = {
num: 0
}
btn = () = > {
this.setState(state= > ({ num: state.num + 1}}}))export default Fun1
Copy the code
State Hooks
Make function components stateful and read and write
Using react.usestate (value) in a functional component returns a 2-bit array. Deconstructing the array returns two arguments, the first for the value you passed in and the second for the method that operated on it. // Function Fun1() {const [num,setNum] = react. useState(0) function BTN (){setNum((num) => {return num+1 SetNum (num => num +1)} return (<div> <h1> num) </h1> <button onClick={BTN}> </div>) } this function will be called 1+n times every time the value changes as you click on it, but every time it does React. UseState (0) that value will always be 0Copy the code
Effect Hooks Life cycle Hooks
Write directly in the function component function
React.useEffect(() = >{log(equivalent to render)}) React. UseEffect (() = >{log(equivalent to didmount)},[]) react.useeffect (() = >},[num,name]) react. useEffect(() = > {
let timer = setInterval(()={
xxxxxxxx
},1000)
return () = >{ clearInterval(timer) } // The returned willUnmount will be unmounted}, [])Copy the code
Ref Hooks
Similar and createRef ()
/ / function type
function Fun1(props) {
const myRef = React.useRef()
React.useEffect(() = >{})function show(){
console.log(myRef.current.value);
}
return (
<div>
<input type="text" ref={myRef} />
<button onClick={show}>button</button>
</div>)}Copy the code
Extension API
Fragment
When a tag can also be null the tag can only receive one key attribute but not the other
import {Fragment} from 'react' class xxx extends React.Component { render() { return ( <Fragment key={1}> {this.state.num}</h1> <button onClick={this.btn}> </button> </Fragment>} class XXX extends React.Component { The render () {return (< > < h1 > Numbers {this. State. Num} < / h1 > < button onClick = {this. BTN} > I + 1 < / button > < / a >)}Copy the code
Contex component communication mode
The actual combat generally does not only use it encapsulated third-party kuzu component and descendant component communication
Const XxxContext = react.createcontext () 2. When rendering a component, wrap the xxxContext.provider around it, Provider value={data}> child component </xxxContext.Provider value={data}> 3. The child of the descendant reading data child can also take the first type directly: < xxxContext.consumer > {value => {static contextType = xxxContext // declare to receive this. Context // Read the value of the context. }} </ xxxcontext.consumer >Copy the code
The son component receives the code
const MyContext = React.createContext() // Create a container object
// Class components
class Fun2 extends React.Component {
render() {
return (
<div>
<h1>I am the ancestor component</h1>
<MyContext.Provider value={this.state.name}>{/* Pass can also pass objects */}<FunFather/>
</MyContext.Provider>
</div>
)
}
state = {
name:'hello'}}class FunFather extends React.Component {
render() {
console.log(this.context); / / how are you
return (
<div>
<h3>I'm the parent component</h3>
<FunSon></FunSon>
</div>)}static contextType = MyContext / / declare
}
// Class child components receive code
class FunSon extends React.Component {
render() {
return (
<h3>I am the son component {this.context}</h3>)}static contextType = MyContext / / declare
}
// The function child component receives code
function FunSon() {
return (
<h3>I am the son component<MyContext.Consumer>
{
(value) => { return value }
}
</MyContext.Consumer>
</h3>)}Copy the code
PureComponent component optimization
Two problems with Component
- As long as setState() is executed, even without changing the state data, rerender == is inefficient
- When the current component is rerendered, the child component is automatically rerendered, even if the child component does not use any data from the parent component
It is efficient to re-render only if the state or props data for the current component changes
The reason shouldComponentUpdate in Component always returns true
To solve
ShouldComponentUpdate () method to compare old and new state/props data, return true if there is any change, false if there is no change PureComponent shouldComponentUpdate returns true only if the state or props are changed. This is a shallow comparison. If the internal data of the knowledge data object has changed, return false so do not directly modify the state data, but instead generate new data that cannot be the same addressCopy the code
Solution 1 can only compare the values in the props or state one by one
// The parameters are props and state to be changed next
shouldComponentUpdate(nextProps,nextState){
if(nextState.car === this.state.car){
// If the next step is the same as the current one, it will not render
return false
}
return true
}
/ / short
shouldComponentUpdate(nextProps,nextState){
return! (nextState.car ===this.state.car)
}
Copy the code
Solution 2
import React from 'react'Change react.componentto react.pureComponentclass Parent extends React.PureComponentNotes //PureComponentThe bottom layer decidesobj = = =thisThe state?const obj = this.state // point to the same address
obj.car = maybach
this.setState(obj) // The underlying PureComponent will say obj === this.state?So this is going to fail because obj andthisThe address of state is the same as that of renderthis.setState({
car: maybach}) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- such as a stus in the stateconst {stus} = this.state // point to the same address
stus.unshift('xiao li')
this.setState({stus:stus}) so this way will modify failed addresses that are the same as PureComponent the underlying layer will judge the same will not render like thisconst {suts} = this.state
this.setState({stus: ['xiao li'. stus]})// You can also use arrays, shallow copies of objectsNewArr = [...arr] newObj =JSON.parse(JSONAbout stringify (obj))JSON.parse(JSON.stringify(obj)) implements some deep copy pitshttps://segmentfault.com/a/1190000020297508?utm_source=tag-newest
Copy the code
RenderProps slot
In addition to the traditional father putting A and B in A, there is another form of father and child
The array that childrenProps B needs for A is not received
class Parent extends React.PureComponent {
render() {
return (
<div>
<h1>I'm the parent component</h1>
<A>{/* if a is the props of b, b will be the children of a */<B></B>
</A>
</div>)}}class A extends React.PureComponent {
render() {
return (
<div>
<h3>I'm A child of A</h3>{this.props. Children} {/* Get the children of props */}</div>)}}class B extends React.PureComponent { render() { return <h3>I'm a child of B</h3>}}Copy the code
RenderProps, dynamically passing content destructions inside components (tags)
class Parent extends React.PureComponent {
render() {
return (
<div>
<h1>I'm the parent component</h1>
<A render={()= > <B />} ></A>{/* Pass a callback function to a */}</div>)}}class A extends React.PureComponent {
render() {
return (
<div>
<h3>I'm A child of A</h3>{this.props. Render ()} {/* props.</div>)}}class B extends React.PureComponent { render() { return <h3>I'm a child of B</h3>}}Copy the code
Callback function data transmission value
// Class components
class Parent extends React.PureComponent {
render() {
return (
<div>
<h1>I'm the parent component</h1>
<A render={(name)= > <B name={name} />} ></A>{/*2. This parameter receives assignment to B*/}</div>)}}class A extends React.PureComponent {
render() {
return (
<div>
<h3>I'm A child of A</h3>{this.props.render(this.state.name)} {/*1. The value passed here */}</div>
)
}
state = { name: 'tom'}}class B extends React.PureComponent { render() { console.log(this.props.name); return <h3>I'm a child of B</h3>}} is equal to a {this.props.render(this.state.name)} <A render={() = > <Some/>} / >Copy the code
Error Boundary
Only errors generated during the life cycle of a descendant component are caught, not errors generated by its own component and compositing events generated by other components. Error bounds generated in timers should be manipulated in the parent component of the error-prone component
// If any child component reports an error, the call is triggered with an error message
static getDerivedStateFromError(err){}
// An error occurred with the neutron component during rendering
compomentDidCatch(){}
// Class components
class Parent extends React.PureComponent {
render() {
return (
<div>
<h1>I'm the parent component</h1>
{this.state.hasError ? <h2>Page fault</h2> : <A />}
</div>
)
}
state = {
hasError: ' ' // Identifies whether the child component has an error
}
// If any child component reports an error, the call is triggered with an error message
static getDerivedStateFromError(err) {
console.log('err', err);
return { hasError: err }
}
}
class A extends React.PureComponent {
render() {
return (
<div>
<h3>I'm A child of A</h3>{this.state.name.map((item) => {// This is an error because the status does not return anything<h1>item</h1>
})}
</div>)}}Copy the code
Summary of component communication modes
Relationships between components
- Father and son
- Brothers (non-nested components)
- Grandparent (Cross-level components)
Communication mode1. props
children props
render props
2.Message subscription publishing pubs-sub, etc3.Centralized management of REDUx, DVA, etc4.Context producer-consumer patternCopy the code
A better way to match
Parent component: props Sibling component: message subscription Grandchild (cross level) : message subscription, centralized, Context (less for development, more for packaging plug-ins)Copy the code