I haven’t been learning React for a long time. If I don’t understand react well, I hope you can give me some advice. Thank you.
Vue vs. React
There are too many articles about the difference between Vue and React. This article is not mainly about this. It is just a casual comment.
The same
- Both are built based on the Virtual DOM
- The idea of componentization
- Both support server-side rendering (what is server-side rendering? Front-end personal understanding and transformation of SEO optimization combat (based on VUE-SSR)
- There are vue-vuex, react-redux and react-redux state management schemes.
- They all have a life cycle (although the way to say life cycle is different)
The difference between
- DefindPropety for Vue2 and proxy-es6 for Vue3. React for one-way data flow (this.$setState is used to modify data)
- Vue uses Html+Css+Js, while React uses all-in-one Js.
- Different rendering methods for virtual DOM (different contrast methods)
Others can dig gold / 100 degrees (here recommended two)
Personally understand the difference between Vue and React
Vue is different from React
Whether to use Vue or React is a matter of opinion. Use whichever you like (actually, you use whichever the company uses). Vue is faster to learn than React because a lot of things are encapsulated (e.g., route-hijacking). React, on the other hand, is relatively expensive to learn and requires a lot of things to be encapsulated. .
The React based
Install and use
First of all, I think we need a project. Otherwise, how can we meet the familiar Hello World? usenpx create-react-app react-demo
Create a project, directory it and run it, and delete some of the leftovers (not needed yet), something like this
Begin to learn
The most basic components
Because React is the idea of everything being a component. React+Redux: React+Redux: React+Redux: React+Redux: React+Redux
Stateless component
Stateless? LPL player? Ha, ha, ha, ha. A stateless component in React refers to a function component (with no lifecycle, hook will be described later). It is used to receive props from the parent component and define templates to display data. Interaction/business operations are not recommended because this ensures high reusability and improves rendering performance.
Create a new folder (demo01) and put an index.js in it (I won’t mention this later)
// JSX must include React, not Fragment. The Fragment is like a placeholder. When React is rendered to the browser, the Fragment will not be rendered
import React, { Fragment } from 'react';
// All components must start with a lowercase letter. Use uppercase to import components. React will treat components that start with lowercase as native HTML tags
function Sateless(props) {
return (
// The outermost layer must have only one root element - similar to Vue's
<Fragment>
<div>I'm a stateless component with no cards</div>{/* this is a function of JSX props, which is a function of the parent component.<div>{props.num}</div>
<div>{props.text}</div>
</Fragment>)}// Remember to export
export default Sateless;
Copy the code
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// Remember uppercase here
import Sateless from './demo01';
ReactDOM.render(
<React.StrictMode>The value * /} {/ *<Sateless num={666} text={'MY name is stateless '}/>
</React.StrictMode>.document.getElementById('root'));Copy the code
Stateful component
If there is no state, there is state. It is unlikely that all components are not recommended for interaction/business operations. Stateful components are classes that have a life cycle and support interaction/business operations, but are expensive to render.
Write a classic demo, plus 1 minus 1. Ha, ha, ha
// Also extends Component extends Component extends React.Com
import React, { Component } from 'react';
class Stateful extends Component {
constructor(props) {
super(props);
// Set the initial value
this.state = {
count: 0
}
// The first way to bind this. In JavaScript, class methods do not bind this by default.
// If you forget to bind and pass it onClick, this will be undefined when you call this function.
this.addFunc = this.addFunc.bind(this)}componentWillMount() {
console.log('I'm going to show you the life cycle, and I'll talk about it later.')
console.log('componentWillMount111')}componentDidMount() {
console.log('componentDidMount222')}addFunc() {
// One way to write an assignment
this.setState({
count: this.state.count + 1})}subFunc() {
// Another way of writing assignment (why this is used below)
this.setState((preState) = > {
return {
count: preState.count - 1}})}setZero() {
this.setState({
count: 0})}render() {
return (
<div>
<div>I am a stateful component</div>
<div>{this.state.count}</div>
<div>
<button onClick={this.addFunc}>+ 1</button>{/* The second way to bind this */}<button onClick={this.subFunc.bind(this)}>- 1</button>{/* The third way to bind this */}<button onClick={()= >{this.setzero ()}}> return to 0</button>
</div>
<div>I can also accept values from the parent component: {this.props. Text}</div>
</div>); }}export default Stateful;
Copy the code
It’s introduced the same way, and it looks like this
setState
As we said above,this.setState()
There are different ways. It doesn’t really count. Except it can take two arguments, the first can be an object or a function, and the second can take a callback or be null (most of the time we are null). Look at theThe official instructions”, here mention too much, see the specific official, said more detailed, I do not want to CV so many things directly over.The following three operations are equivalent to only one operation
// It looks like it will execute three times, but react will merge them into one
testFunc() {
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 });
this.setState({ count: this.state.count + 1 });
}
Copy the code
The second argument accepts a callback function, which is executed when the data is updated (so there is no asynchronous problem, I think).
The life cycle
-
ComponentWillMount is called before rendering, both on the client side and on the server side.
-
ComponentDidMount: Called after the first rendering, only on the client side. The component then generates the corresponding DOM structure, which can be accessed through this.getDomNode (). If you want to use it with other JavaScript frameworks, you can use this method to call setTimeout, setInterval, or send AJAX requests (to prevent asynchronous operations from blocking the UI).
-
ComponentWillReceiveProps component receives a new prop (updated) is invoked. This method is not called when render is initialized.
-
ShouldComponentUpdate returns a Boolean value. Called when the component receives new props or state. Not called during initialization or when forceUpdate is used.
This can be used when you are sure that you do not need to update the component. (This Vue is optimized for us by default)
-
ComponentWillUpdate is called when the component receives a new props or state but has not yet rendered. Will not be called during initialization.
-
ComponentDidUpdate is called immediately after the component has finished updating. Will not be called during initialization.
-
ComponentWillUnmount is called immediately before the component is removed from the DOM
If you have learned Vue, you probably know what each of these represents. I won’t go into details here, but I will go into details if it is mentioned below.
Conditions apply colours to a drawing
Here’s another classic example, Todolist.
import React, { Component } from 'react'
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: ' '.todoList: [{id: 1.text: 'learning Vue' },
{ id: 2.text: 'learning React' },
{ id: 3.text: 'learning presents']}},this.changeValueFunc = this.changeValueFunc.bind(this)
this.addNewListItem = this.addNewListItem.bind(this)
this.delItem = this.delItem.bind(this)}changeValueFunc(e) {
const inputValue = e.target.value
this.setState({
inputValue
})
}
addNewListItem() {
if (!this.state.inputValue) {
return;
}
const value = this.state.inputValue;
this.setState({
todoList: [...this.state.todoList, { id: this.state.todoList.length + 1.text: value }],
inputValue: ' '})}delItem(index) {
let newList = this.state.todoList
newList.splice(index, 1)
this.setState({
todoList: newList
})
}
render() {
let { inputValue, todoList } = this.state
return (
<div>
<input type="text" value={inputValue} onChange={this.changeValueFunc} />
<button onClick={this.addNewListItem}>Let go of me. I have to study</button>
<ul>{/ * traversal * /} {todoList. The map (/ / by the method of transfer (item, index) = ><li onClick={()= > { this.delItem(index) }} key={item.id}>{item.text}</li>
)}
</ul>
{
todoList.length >= 5 ? <h1>Here we go. Stop studying</h1> : null
}
</div>); }}export default TodoList;
Copy the code
Why use Key? I’m sure you know why (as with Vue). If you don’t know, you can go to the official instructions
The basic is here, if there is a slowly up, mainly because I began to learn notes missing, all to write again or very annoying, some notes to write what also forget.
The React advanced
slot
Common usage (anonymous slot)
import React, { Component } from 'react'
class Slot extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
console.log(this.props.children)
return (
<div>
<div>I am my own person</div>{/* react is used to get props. Children */} {this.props. Children}</div>); }}export default Slot;
Copy the code
scr/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Slot from './demo05';
ReactDOM.render(
<React.StrictMode>
<Slot>
<div>I was the first one to pass it on</div>
<div>I was the second one to pass</div>
<div>I was the third one to pass</div>
</Slot>
</React.StrictMode>.document.getElementById('root'));Copy the code
Advanced usage (named slot)
Named slots are implemented using an attribute of the this.props. Children neutron component
import React, { Component } from 'react'
class Slot extends Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
let nameSlot = {};
// Extract the named slot
this.props.children.forEach(item= > {
if(item.props.slot) { nameSlot[item.props.slot] = item; }})return (
<div>
<div style={{ color: 'red' }}>
{nameSlot['nameSlotOne']}
</div>{/ * filter not named slots * /} {this. Props. Children. Filter (item = >! item.props.slot)}<div style={{ color: 'red' }}>
{nameSlot['nameSlotTwo']}
</div>
</div>); }}export default Slot;
Copy the code
scr/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Slot from './demo05';
ReactDOM.render(
<React.StrictMode>
<Slot>
<div>I'm the first anonymous slot</div>
<div>I'm the second anonymous slot</div>
<div>I'm the third anonymous slot</div>
<div slot="nameSlotOne">I'm the first named slot</div>
<div slot="nameSlotTwo">I'm the first named slot</div>
</Slot>
</React.StrictMode>.document.getElementById('root'));Copy the code
hook
What is a hook? Or why hook? It’s official
It lets you use state and other React features without having to write a class
Hook Official Description
Because we know there are no lifecycle and this.setstate () methods in stateless components, hooks help us implement them (Hooks can only be used in stateless components, not class components, and will report errors). Here I will talk about a few simple hooks, because some of my some are still watching……
useState
This can be interpreted as the this.setstate () we use in stateful components, so rewrite the + 1-1 example with a hook
// Remember to introduce useState
import React, { useState } from 'react'
function HookC() {
//useState takes an argument, which is the initial value. Here's how es6 deconstructs an assignment: useState() returns an array
const [count, setCount] = useState(0)
/ / es5 writing
// const countArr = useState(0)
// const count = countArr[0]
// const setCount = countArr[1]
return (
<div>
<div>{count}</div>
<button onClick={()= > { setCount(count + 1) }}>+1</button>
<button onClick={()= > { setCount(count - 1) }}>-1</button>
<button onClick={()= >{setCount(0)}}> return to 0</button>
</div>)}export default HookC
Copy the code
Doesn’t the code look a lot less
useEffect
The official instructions
If you’re familiar with React class lifecycle functions, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount.
One thing to keep in mind
Will useEffect be executed after every render? Yes, by default, it is executed after the first render and after every update. (We’ll talk about how to control it later.) You might be more comfortable with the idea that an effect happens “after rendering,” without having to worry about “mount” or “update.” React ensures that the DOM is updated every time an Effect is run
So let’s just build on that
// Plus this piece in the function
useEffect(() = >{
console.log('Load successful')})Copy the code
We found that it seemed to be executed many times, and cleaning or effecting after each render could cause performance problems. So we need to change it to the control code
useEffect(() = >{
console.log('Load successful')
},[])
Copy the code
Now, we can see that we don’t have that situation anymore, because the second argument is that it fires when the value in the array changes, but now there’s no value in the array, so if you want to fire, you can say this
useEffect(() = >{
console.log('Load successful')
},[count])
Copy the code
routing
The React route has the same history and hash modes as the Vue route. The following uses hash mode as an example
The installation
npm install react-router-dom --save
Basic usage
Create three new files demo07/index.js, demo07/about.js and demo07/main.js
demo07/index.js
import React from 'react'
import {HashRouter as Router,Route,Link} from 'react-router-dom'
import AboutC from './about'
import Mainc from './main'
function RouterC(){
return(
<Router basename='/RouterC'>
<div>I'm the RouterC page</div>
<Link to='/AboutC'>Go to the about page</Link>
<Link to='/Mainc'>Go to the mian page</Link>
<Route path='/AboutC' component={AboutC}></Route>
<Route path='/Mainc' component={Mainc}></Route>
</Router>)}export default RouterC
Copy the code
demo07/about.js
import React,{Component} from 'react'
class AboutC extends Component {
constructor(props) {
super(props);
}
// Triggered when the component is removed
componentWillUnmount(){
console.log('I'm AboutC page, I've been removed')}render() {
return (
<h1>I am AboutC page</h1>); }}export default AboutC;
Copy the code
demo07/main.js
import React from 'react'
function MainC(){
return(
<h1>I'm the Main page</h1>)}export default MainC
Copy the code
scr/index.js
import React from "react"
import ReactDOM from "react-dom"
import "./index.css"
import App from './App'
import RouterC from "./demo07"
import { HashRouter as Router, Route, Link } from 'react-router-dom'
ReactDOM.render(
<Router>
<div><Link to='/'>Home page</Link></div>
<div><Link to='/RouterC'>RouterC page</Link></div>
<Route path='/' exact component={App}></Route>
<Route path='/RouterC' component={RouterC}></Route>
</Router>.document.getElementById("root"))Copy the code
We use exact in SCR /index.js. What does this mean?
Exact is an attribute of Route, which is regarded as a strict matching pattern
If exact is false, all components are matched based on the route. For example, / matches /, /home, and /home/menu. If exact is true, / matches only/and /home cannot be matched.
If you take away exact, you get this
Advanced usage (parameter passing)
Change the index.js file of demo07
<Router basename='/RouterC'>
<div>I'm the RouterC page</div>
<Link to='/AboutC/838182202'>Go to the about page</Link>
<Link to='/Mainc? id=838182202'>Go to the mian page</Link>
<Route path='/AboutC/:id' component={AboutC}></Route>
<Route path='/Mainc' component={Mainc}></Route>
</Router>
Copy the code
about.js
import React,{Component} from 'react'
class AboutC extends Component {
constructor(props) {
super(props);
console.log(this.props)
}
componentWillUnmount(){
console.log('I'm AboutC page, I've been removed')}render() {
return (
<div>
<h1>I am AboutC page</h1>
<div>I passed through the routing and come over: id is {this. Props. Match. Params. Id}</div>
</div>); }}export default AboutC;
Copy the code
main.js
import React from 'react'
function MainC(props){
console.log(props.location.search)
const id = GetQueryValue1(props.location.search,'id')
return(
<div>
<h1>I'm the Main page</h1>
<div>Id is {id}</div>
</div>)}function GetQueryValue1(url,queryName,) {
let reg = new RegExp("(^ | &)" + queryName + "= (/ ^ & *) (& | $)"."i");
let r = url.substr(1).match(reg);
if( r ! =null) {return decodeURI(r[2]);
}else{
return null; }}export default MainC
Copy the code
Others please dig gold/BaiduOther references
The use of the story
I wanted to write another article about it, but I thought it would be better to put it together, so I put it together.
What is? Why?
I quote from God Nguyen Yifeng’s blog about Redux
To be clear, Redux is a useful architecture, but you don’t have to use it. In fact, for the most part, you can do without it and just React. Someone once said this sentence. “If you don’t know if you need Redux, you don’t need it.” “You only need Redux when React isn’t really a solution.”
Simply put, if your UI layer is very simple and doesn’t have a lot of interaction, Redux is unnecessary and adds complexity. The way users are used is very simple there’s no collaboration between users there’s no heavy interaction with the server, there’s no WebSocket View layer and you get data from a single source ** There’s no need for Redux in any of these cases. **
Multiple users can collaborate with each other and interact with the server in large quantities, or use WebSocket View to fetch data from multiple sources. These are the scenarios for Redux: multiple interactions, multiple data sources. ** From a component perspective, consider using Redux if your application has the following scenarios. **
The state of a component, you need to share a state you need to be able to get a component anywhere you need to change the global state of a component you need to change the state of another component
Basic usage
The installation
npm install redux
use
Create a new store.js file in the SRC directory
import { createStore } from 'redux';
// Set the default value
const defaultState = {
count: 0
}
/ / processor
const reducerFunc = (state = defaultState, action) = > {
let newState = JSON.parse(JSON.stringify(state))
switch (action.type) {
case 'add_num': newState.count = state.count + 1;
return newState;
case 'sub_num': newState.count = state.count - 1;
return newState;
case 'zero_num': newState.count = 0;
return newState;
default: return newState
}
}
const store = createStore(reducerFunc);
export default store
Copy the code
Let’s take the counter for example
import React,{Component} from 'react'
import store from '.. /store'
class CountC extends Component {
constructor(props) {
super(props);
// the stroe method to get the value
this.state = store.getState();
// Trigger when stroe data changes
store.subscribe(() = >{
this.setState( store.getState())
})
}
addFunc(){
Distributed / / action
store.dispatch({
type:'add_num'})},subFunc(){
store.dispatch({
type:'sub_num'})},zeroFunc(){
store.dispatch({
type:'zero_num'})},render() {
return (
<div>
<div>{this.state.count}</div>
<button onClick={this.addFunc.bind(this)}>+ 1</button>
<button onClick={this.subFunc.bind(this)}>- 1</button>
<button onClick={this.zeroFunc.bind(this)}>Return 0</button>
</div>); }}export default CountC;
Copy the code
src/index.js
import React,{Component} from "react"
import ReactDOM from "react-dom"
import "./index.css"
import App from './App'
import CountC from "./demo08"
import store from './store'
class TestC extends Component {
constructor(props) {
super(props);
this.state = store.getState();
store.subscribe(() = >{
this.setState( store.getState())
})
}
render() {
return (
<div>{this.state.count}</div>
);
}
}
ReactDOM.render(
<div>
<div><CountC></CountC></div>
<TestC></TestC>
</div>.document.getElementById("root"))Copy the code
Code optimization
It is ok to do that, but when we have a reducer number of our processor, and the action. Type should also be defined by constant, otherwise there will be no error writing, and we had better create another file to create action. So, we’re going to create a store file under the Demo folder, and we’re going to take care of its store management and we’re going to look at the directory actionType.js
export const ADD_NUM = 'ADD_NUM';
export const SUB_NUM = 'SUB_NUM';
export const ZERO_NUM = 'ZERO_NUM';
Copy the code
createAction.js
// Create your own action
import { ADD_NUM, SUB_NUM, ZERO_NUM } from './actionType'
export const addNumAc = () = > {
return {
type: ADD_NUM
}
}
export const subNumAc = () = > {
return {
type: SUB_NUM
}
}
export const zeroNumAc = () = > {
return {
type: ZERO_NUM
}
}
Copy the code
reducer.js
// Handle your own, not others
import { ADD_NUM, SUB_NUM, ZERO_NUM } from './actionType'
const defaultState = {
count: 0
}
export const countReducer = (state = defaultState, action) = > {
let newState = JSON.parse(JSON.stringify(state))
switch (action.type) {
case ADD_NUM: newState.count = state.count + 1;
return newState;
case SUB_NUM: newState.count = state.count - 1;
return newState;
case ZERO_NUM: newState.count = 0;
return newState;
default: return newState
}
}
Copy the code
store/index.js
// Export all files
import * as actionType from './actionType'
import * as creactAction from './createAction'
import { countReducer } from './reducer'
export default countReducer;
Copy the code
Counter partial modification
constructor(props) {
super(props);
// the stroe method to get the value
this.state = store.getState().countReducer;
// Trigger when stroe data changes
store.subscribe(() = >{
this.setState( store.getState().countReducer)
})
}
addFunc(){
/ / distributing
store.dispatch(addNumAc())
}
subFunc(){
store.dispatch(subNumAc())
}
zeroFunc(){
store.dispatch(zeroNumAc())
}
Copy the code
src/store.js
import { createStore, combineReducers } from 'redux';
import countReducer from './demo08/store'
/ / combineReducers used to connect multiple reducer We can also names ({a: countReducer}) writes
const allReducer = combineReducers({ countReducer })
// The second parameter below is configured using Chrome plugin, if not, can be removed directly
const store = createStore(allReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());
export default store
Copy the code
Run it, ok.
Middleware story – thunk
In this video we’ll switch to Todolist to show that Ann is modifying the code as she did in the last videoModify the createAction.js code (let’s add asynchronous operations)
import { ADD_ITEM, DEL_ITEM, CHANGE_VALUE } from './actionType'
export const changeValueAC = inputValue => {
setTimeout(() => {
return {
type: CHANGE_VALUE,
inputValue
}
}, 1000)
}
export const addItemAc = () => {
return {
type: ADD_ITEM
}
}
export const delItemAc = index => {
return {
type: DEL_ITEM,
index
}
}
Copy the code
Then found the page reported the following error
Actions must be plain objects. Use custom middleware for async actions.
The translation is that actions must be ordinary objects. Use custom middleware for asynchronous operations so redux-Thunk is designed to solve this problem
The installation
npm install redux-thunk
use
src/store.js
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import countReducer from './demo08/store'
import todoListReducer from './demo09/store'
/ / combineReducers used to connect multiple reducer We can also names ({a: countReducer}) writes
const allReducer = combineReducers({ countReducer, todoListReducer })
const composeEnhancers =
typeof window= = ='object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(thunk),
);
const store = createStore(allReducer, enhancer);
// If the plugin is not used, just write it like this
// const store = createStore(allReducer, applyMiddleware(thunk));
export default store
Copy the code
CreateAction. Js modified
export const changeValueAC = inputValue= > {
return dispatch= > {
setTimeout(() = > {
console.log('1')
dispatch({
type: CHANGE_VALUE,
inputValue
})
},1000)}}Copy the code
todolist
changeValueFunc(e) {
const inputValue = e.target.value
store.dispatch(changeValueAC(inputValue))
}
Copy the code
react-redux
React-redux is a redux library created by the author of Redux. The following three methods can be directly described by Ruan Yafen’s blog.
connect()
React-redux provides the connect method for generating container components from UI components. Connect means to connect the two components together.
mapStateToProps()
MapStateToProps is a function. Its job, as its name suggests, is to establish a mapping between the (external) state object and the (UI component’s) props object.
mapDispatchToProps()
MapDispatchToProps is the second parameter to the connect function that maps UI component parameters to the Store. dispatch method. That is, it defines which user actions should be passed to the Store as actions. It can be a function or an object.
use
Let’s go ahead and modify the example above. todolist
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {changeValueAC,addItemAc,delItemAc} from './store/createAction'
class TodoList extends Component {
render() {
let { inputValue, todoList } = this.props
return (
<div>
<input type="text" value={inputValue} onChange={this.props.changeValueFunc} />
<button onClick={this.props.addNewListItem}>Let go of me. I have to study</button>
<ul>
{todoList.map(
(item, index) => <li onClick={()= > { this.props.delItem(index) }} key={item.id}>{item.text}</li>
)}
</ul>
{
todoList.length >= 5 ? <h1>Here we go. Stop studying</h1> : null
}
</div>); }}const mapStateToProps = (state) = >{
let {inputValue,todoList} = state.todoListReducer
return {
inputValue,todoList
}
}
const mapDispatchToProps=(dispatch,ownProps) = >{
return {
changeValueFunc(e) {
const inputValue = e.target.value
dispatch(changeValueAC(inputValue))
},
addNewListItem() {
dispatch(addItemAc());
},
delItem(index){ dispatch(delItemAc(index)); }}}export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
Copy the code
Slip slip slip, write here first, follow up to see the situation continue to supplement