What are Hooks?
-Blair: That’s what I learned from the Hooks. Functions that allow you to “hook” React state and lifecycle features into function components. React 16.8 is a new feature. It lets you use state and other React features without having to write a class.
What it does: Provides functions to function components, such as state and life cycles, that are originally provided in Class components
- Hooks can only be used in function components
- Can be understood as hooking the class component’s features for the function component via Hooks
Comparison of component development patterns before and after Hooks
-
React V16.8 before: Class component (provides state) + function component (displays content)
-
React V16.8 and later:
- Class component (provides state) + function component (presents content)
- Hooks(provide state) + function components (display content)
- Mix these two approaches: use class components for some functions, Hooks+ function components for some functions
Why Hooks
Two perspectives: 1 component state logic reuse 2 class component itself problems
The essence of the React component
React is a JavaScript library for building user interfaces.
The React component encapsulates specific functions and is mainly used to split the UI.
The React component Model is a straightforward mapping from Model to View. The Model corresponds to the React function as state and props
Formula: Component (State+Props) = UI
Problems with the class component itself
The class component does not perform its most important function in rendering the UI by state:
- Components rarely inherit from one another
- Components rarely visit each other
Benefits of functional components
- The function itself is simpler and better able to render the UI based on state
- Hooks give function components the ability to maintain state internally
- Hooks bring logical reuse capabilities to components
Use policy for hooks
strategy
-
React has no plans to remove classes from React
-
Hooks and existing code work together, and you can use them incrementally:
- Large-scale refactoring of existing components directly using Hooks is not recommended
- Hooks are recommended for new functions. If complex functions cannot be implemented, use class
- Find a simple, non-core component and start using hooks
-
Class component-related apis are not used in hooks
- The state and setState
- Hook function,
componentDidMount
,componentDidUpdate
,componentWillUnmount
`this
Related usage
-
The original learning content is still to use
- JSX:
{}
,onClick={handleClick}
, conditional rendering, list rendering, style processing, etc - Component: function component, component communication
- React development concept:
Unidirectional data flow
,State of ascension
等
- JSX:
UseState – Basic use – Learn the first hooks
You can use useState to provide state for function components
Usage scenarios
Use the useState Hook when you want to use component state in a functional component
role
Provide state for function components
steps
-
Import the useState function
-
Call the useState function, passing in the initial value, returning the state, and a function to modify the state
-
use
- Displayed in JSX
state
- Call the function that modifies the state at a specific time to change the state
- Displayed in JSX
You look at
import { useState } from 'react'
// useState is a hook, hook is a function starting with use
const Count = () = > {
// 0 is the initial value
The return value is an array
const stateArray = useState(0)
// Status value -> 0
const state = stateArray[0]
// A function to modify the state
const setState = stateArray[1]
return (
<div>{/* Display status values */}<h1>useState Hook -> {state}</h1>{/* Click the button to make the status value +1 */}<button onClick={()= > setState(state + 1)}>+1</button>
</div>)}Copy the code
-
Parameter: initial status value. For example, passing a 0 indicates that the initial value of the state is 0
- Note: The state here can be any value (for example, value, string, etc.), and the state in the class component must be an object
-
Return value: array, containing two values: 1 state value (state) 2 Function to modify the state (setState)
Use array deconstruction to simplify code
Use array deconstruction to simplify useState. Convention: The name of the function that changes the state begins with set, followed by the name of the state
// The name can be any name
const [state, setState] = useState(0)
const [age, setAge] = useState(0)
const [count, setCount] = useState(0)
Copy the code
UseState – Handles form elements
- Use useState to initialize content and modify content methods
- Set the value and onChange attributes to the input element
The ground sample
import React, { useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
const [content, setContent] = useState(' ')
return (
<div>
{content}
<input value={content} onChange={(e)= > setContent(e.target.value)} />
</div>
)
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code
UseState callback function format
UseState two formats
Format 1: Pass the value
useState(0) useState('abc')
Format 2: Incoming callback
UseState (() => {return initial value})
- The return value of the callback function is the current value of the state
- The callback function fires only once
Usage scenarios
Format 1: Pass the value
If the state is just plain data (for example, string, number, array, etc.) you can use useState directly (plain data)
Format 2: Incoming callback
- The initial state takes some calculation.
UseState (()=>{here is some calculation, return result}))
SetXXX can be a callback
States need to be accumulated iteratively. SetXXXXX ((last value) => {return new value})
Example – Classic scenario
We want the state to have the effect of continuous superposition
import React, { useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
const [count, setCount] = useState(0)
const hClick1 = () = > {
setCount(count+1)
setCount(count+1)
setCount(count+1)}const hClick2 = () = > {
setCount((count) = >count+1)
setCount((count) = >count+1)
setCount((count) = >count+1)}return (
<div>
count:{count}
<button onClick={hClick1}>Multiple consecutive setCount- values</button>
<button onClick={hClick2}>Multiple consecutive setCount- values</button>
</div>
)
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code
summary
-
Parameters for useState come in two formats
- value
const [count, setCount] = useState(0)
- The callback function
Const [count, setCount] = useState(()=>{return initial value})
- value
-
Arguments to setXXX have two formats, where functions can be used to superimpose state
setCount(100)
setCount(initState= > {
// ...
return newState
})
Copy the code
demo
// Countdown demo
import React, { useState } from 'react'
import ReactDOM from 'react-dom'
export default function App () {
const [count, setCount] = useState(10)
console.log(count, setCount)
const hClick = () = > {
console.log(11)
const time = setInterval(() = > {
setCount((count) = > {
if (count === 1) {
clearInterval(time)
}
return count - 1})},1000)}return (
<div>
<p>The countdown</p>
<h1>{count}</h1>
<button onClick={hClick}>The countdown</button>
</div>
)
}
ReactDOM.render(<App />.document.getElementById('root'))
Copy the code
UseState – Component update process
background
Function components have no life cycle
The update process
The sample code
import { useState } from 'react'
const Count = () = > {
console.log('Count... ')
const [count, setCount] = useState(0)
return (
<div>{/* Display status values */}<h1>useState Hook -> {count}</h1>{/* Click the button to make the status value +1 */}<button onClick={()= > setCount(count + 1)}>+1</button>
</div>)}Copy the code
The update process
Use useState Hook to execute the function component and change the state value:
-
Component first render:
- Execute the code logic in the function
- call
useState(0)
Take the parameter passed as the initial value of the state, which is: 0 - Render component, at this point, the acquired state count value is: 0
The user clicks the button and calls setCount(count + 1) to change the state. As the state changes, the component is re-rendered
-
Component second render:
-
Execute the code logic in this component again
-
Call useState(0) again:
- React gets the latest state value instead of the initial value
- The latest status value in this case is 1
-
Render the component again, at which point the obtained state count value is: 1
-
The initial value (parameter) of useState only takes effect when the component is first rendered
const [count, setCount] = useState(() = >{
console.log('useState... ') // This sentence will be output only once
return 0
})
Copy the code
That is, useState gets the latest state value for each subsequent render. The React component remembers the latest state value each time!
summary
Status updates, where the logic of the entire component is run again;
UseState only uses the initial value of the state for the first rendering of the component, and then the latest value of the state
The useState Hook is used to manage state, which enables function components to maintain state. That is, the state is shared between multiple renders of a function component.
How do I provide multiple states for function components?
Two kinds of schemes
- Plan 1:
UseState ({state 1, state 2..... })
- Scheme 2:
UseState (State 1) useState(State 2)
Scheme 2 is recommended
You can call useState Hook several times, and each time you call useState Hook you can provide one state.
Note:
Hooks: setXXX(new value) ==> Replace previous value with new value
Class: setState({attribute to modify})
Rules for using useState
The rules
-
UseState can only appear directly inside a function component
-
UseState cannot be nested in if/for/
Reason: React identifies each Hook according to the sequence in which Hooks are called. If the sequence is different, React cannot know which Hook it is. You can view it through the developer tools
UseEffect – Understand side effects
Functional components:
- Render UI based on data (state/props)
- Side effects: Data (Ajax) requests, manual DOM modification, start timer, empty timer, add event listener, delete event, localStorage operation, etc
conclusion
For the React component, anything other than rendering the UI is a side effect.
UseEffect – Basic use
Using the step
1. Import useEffect
import { useEffect } from 'react'
// 2. Use useEffect
useEffect(() = > {
console.log('useEffect 1 executed, can do side effects')
})
useEffect(() = > {
console.log('useEffect 2 executed, can do side effects')})Copy the code
Execution time
After the render job is done, Effect is executed;
If multiple definitions are specified, they are executed in sequence.
case
import React, { useState, useEffect } from 'react'
import ReactDom from 'react-dom'
export default function App () {
useEffect(() = > {
console.log('useEffect')
document.title = 'count' + count
})
const [count, setCount] = useState(0)
return (
<div
onClick={()= >{setCount(count + 1)}}> Function component {count}</div>
)
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code
UseEffect – Sets dependencies
UseEffect dependencies
UseEffect takes two parameters:
Parameter 1: Side effect function.
Parameter 2: The dependency to execute the side effect function: It determines when to execute parameter 1 (side effect function)
UseEffect complete format
Case 1: No second argument. Timing: Execute after each update
Case 2: Takes a second argument, which is an empty array. Execution time: This parameter is executed for the first time
useEffect(() = > {
// The contents of the side effect function
}, [])
Copy the code
Usage scenario: 1 Event binding 2 Sending a request to obtain data.
Case 3: Takes a second argument (array format) and specifies a dependency. Execution time :(1) execute once initially. (2) execute once if the value of the dependency changes
useEffect(() = > {
// The contents of the side effect function}, [dependencies1, the dependencies2. ] )Copy the code
The dependency here is the state defined in the component.
Reference:
- UseEffect Complete Guide: Overreacted. IO/zh-Hans/A-C…
UseEffect Sends a request
format
// Use it correctly
useEffect(() = > {
// Define a function
async function fetchMyAPI() {
let url = 'http://something/' + productId
let config = {}
const response = await myFetch(url)
}
/ / invoke it
fetchMyAPI()
}, [productId])
Copy the code
Note: Effect can only be a synchronous function, not async
// Error:
// Do not add async to useEffect
useEffect(async() = > {const res = awiat xxx()
return () = >{}}, [])Copy the code
UseEffect – The return value of the side effects function – clears side effects
The return value of the side effect function
format
useEffect(() = > {
// The contents of the side effect function
returnReturn value of the side effect function}, [])Copy the code
The return value of the side effect function is optional and can be omitted. You can also return a cleanup function to clean up side effects
useEffect(() = > {
// The contents of the side effect function
return() = > {/* Do the cleanup */ } // Clean up the function
}, [])
Copy the code
The execution timing of the cleanup function:
- The cleanup function is executed when the component is unloaded and before the next side effect function call
Example: Execution timing
import React, { useEffect, useState } from 'react'
import ReactDom from 'react-dom'
function Com1 () {
useEffect(() = > {
console.log('Child component side effect function')
return () = >{
console.log('Cleanup function for child component side effect function')}}, [])return <div>Child components</div>
}
export default function App () {
const [isShow, setIsShow] = useState(true)
const [count, setCcount] = useState(0)
useEffect(() = > {
console.log('Contents of the parent component's side effect function')
return () = > {
console.log('Contents of cleanup function for parent component side function')
}
}, [count])
return (
<div>
{isShow && <Com1 />}
<button onClick={()= >setIsShow(! IsShow)} > delete | create child component</button>
<button onClick={()= >SetCcount (count+1)}> Click +1, {count}</button>
</div>
)
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code
Example – Simulate componentWillUnmount
useEffect(() = >{
return () = >{
// Do the cleanup}}, [])Copy the code
summary
Case 1: No second argument. Execution timing: Initial execution, after each update.
Analog componentDidmount + componentDidUpdate
useEffect(() = > {
// The contents of the side effect function
})
Copy the code
Case 2: Takes a second argument, which is an empty array. Execution time: This parameter is executed for the first time.
Simulation componentDidMount
useEffect(() = > {
// The contents of the side effect function
}, [])
Copy the code
Usage scenario: 1 Event binding 2 Sending a request to obtain data.
Case 3: Takes a second argument (array format) and specifies a dependency. Execution time :(1) execute once initially. (2) execute once if the value of the dependency changes
useEffect(() = > {
// The contents of the side effect function}, [dependencies1, the dependencies2. ] )Copy the code
The dependency here is the state defined in the component.
Case 4: The dependency is empty, there is no specific side effect function, and there is a cleanup function for the side effect function
Simulation: componentWillUnMount
useEffect(() = > {
return () = > {
// Side effects function cleanup function, simulated componentWillUnMount}}, [])Copy the code
Custom hooks
define
In addition to using the built-in Hooks, you can also create your own Hooks.
Custom Hooks reuse different state logic for different components.
- Custom Hooks is a function to define the function name must begin with the use, through the function name is the React to use to judge whether Hooks
- Hooks can only be used in function components or other custom Hooks; otherwise, an error is reported!
- Custom Hooks extract component state logic, with different parameters and return values for different functions (as with normal functions)
Usage scenarios
Reuse the component state logic by extracting it into reusable functions (custom Hooks).
Be born code
// museMouse.js
import { useEffect, useState } from 'react'
export default function useMouse() {
// Logical processing
const [position, setPosition] = useState({
x: 0.y: 0,
})
useEffect(() = > {
const move = (e) = > {
setPosition({
x: e.pageX,
y: e.pageY,
})
}
document.addEventListener('mousemove', move)
return () = > {
document.removeEventListener('mousemove', move)
}
}, [])
// Return status
return position
}
Copy the code
UseRef – DOM operation
content
Use scenario: Obtain the DOM when performing DOM operations on the React
Function: Returns a mutable object with the current property through which DOM manipulation can be performed.
const inputRef = useRef(null)
Copy the code
Explanation:
- Parameters: When retrieving the DOM, it is generally set to NULL
- Return value: the object containing the current property.
- Note: Whenever you operate on the DOM in React, you can use the useRef Hook to retrieve the DOM (e.g., the width and height of the DOM).
- Note that useRef can be used to manipulate components as well as the DOM
Core code:
// 1. Import useRef
import React, { useRef } from 'react'
import ReactDom from 'react-dom'
class Com1 extends React.Component {
state = {
a: 100
}
render () {
return <div>com1, {this.state.a}</div>}}export default function App () {
// 2. Call useRef(initial value) to get the reference object
// 3. Set the reference object to any component/element
// 4. Get the component/element by referring to the object.current
const refTxt = useRef(null)
const refCom1 = useRef(null)
console.log(refTxt)
const click = () = > {
console.log(refTxt, refCom1)
console.log(refCom1.current.state.a)
// console.log(refTxt.current.value)
// refTxt.current.style.backgroundColor = 'red'
}
return (
<div>
useRef, <input ref={refTxt} />{'}<button onClick={click}>Click to get the value in the input</button>
<br />
<Com1 ref={refCom1} />
</div>
)
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code
UseRef – Share data between multiple renders
The function component, while intuitive and simplifying the logic of thinking about UI implementation, lacks an important capability compared to the Class component: the ability to share data between multiple renders.
The problem to import
import React, { useEffect, useState } from 'react'
import ReactDom from 'react-dom'
export default function App () {
const [count, setCount] = useState(0)
let timeId = null
console.log(timeId)
useEffect(() = > {
timeId = setInterval(() = > {
setCount((count) = > count + 1)},1000)
console.log(timeId)
}, [])
const hClick = () = > {
console.log(timeId)
clearInterval(timeId)
}
return (
<div>
count:{count}
<button onClick={hClick}>Click stop timer</button>
</div>
)
}
ReactDom.render(<App />.document.getElementById('root'))
Copy the code
Analysis of the
SetCount causes the component to be re-rendered, and when re-rendered, the following code is repeated
let timeId = null
Copy the code
Therefore, you cannot save timeId
Train of thought
Save the timeId in a location that won’t be lost for multiple renders.
steps
// 1. Import useRef
import React, { useRef } from 'react'Components () {// 2. Call useRef,
const timeRef = useRef(null)
// 3. Store data to referenced currentTimeref. current = Data you need to share between multiple renders}Copy the code
UseContext – Global status
UseContext steps
A total of 3 steps:
- Import and call the createContext method to get the Context object and export
import { createContext } from 'react'
export const Context = createContext()
Copy the code
- Wrap the root component with the Provider component and provide the data to be shared through the value property
return (
<Context.Provider value={Put the data to be passed here}>< root component contents />
</Provider>
)
Copy the code
- In any descendant component, if you want to get public data:
Import useContext; Call useContext(the context exported in the first step) to get the value of value
import React, { useContext } from 'react'
import { Context } from './index'
constFunction component =() = > {
constPublic data = useContext(Context)return(Contents of function components)}Copy the code
Bao, you see this will not give me a star?
PS: If there are any mistakes in the content, please point them out (feel uncomfortable to make fun of them); If there is help, welcome to like and collect, please reprint the source, if there is a problem also welcome private communication