Study notes from three latitudes:
- Why 🤔 ️
- How to use 🔨
- Knowledge ⛽ ️
useState
Why use useState?
UseState comes in the form of using class setState in function components, stimulating!
The problem is that when a function component wants to maintain its own state, it has to convert to class. This is troublesome!
How do I use useState?
const [name, setName] = useState('rose')
Copy the code
useState
😄1. Key: The initial value of useState is valid only for the first time
I didn’t take it seriously until I hit a hole…
🌰2. For example:
When I click the button to change the value of name, I find that in the Child component, it is received, but the value is not assigned to name through useState!
Conclusion: Practice test knowledge point! 😭
const Child = memo(({data}) =>{
console.log('child render... ', data)
const [name, setName] = useState(data)
return (
<div>
<div>child</div>
<div>{name} --- {data}</div>
</div>
);
})
const Hook =()=>{
console.log('Hook render... ')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
return(
<div>
<div>
{count}
</div>
<button onClick={()=>setCount(count+1)}>update count </button>
<button onClick={()=>setName('jack')}>update name </button>
<Child data={name}/>
</div>
)
}
Copy the code
useEffect
Why useEffect?
UseEffect is the use of a class lifecycle function in a function component, or a combination of all functions. Exciting!
How do I use useEffect?
useEffect(()=>{
...
})
Copy the code
useEffect
😄1. First time only componentDidMount, can be used to request asynchronous data… ,
UseEffect Finally, the addition of [] indicates only the first execution
UseEffect (()=>{const users = get user info ()},[])Copy the code
😄2. Instead of life functions such as willUpdate that are executed every time you render
UseEffect Finally, without [], every render is executed
UseEffect (()=>{const users = get user info every time ()})Copy the code
😄3. It takes a bit of money to perform every rendering, so:
UseEffect finally, add [], and the field in [] indicates that the field has changed before this effect is executed
UseEffect (() => {const users = (name)},[name])Copy the code
😄4. What if I want to separate name and age:
Multiple useeffects can be written
},[name]) useEffect(() => {const users = (const users =)},[name]) useEffect(() => {const users = },[age]Copy the code
😄5. How to use useEffect if we want to unsubscribe from a subscription during the willUnMount lifecycle:
You can unsubscribe from an effect return
UseEffect (() => {const subscription =return() => {cancel the subscription to the national people eat information! }}, [])Copy the code
Why unsubscribe?
UseEffect is used after render. If useEffect has a setInterval… Every time render is rendered, useEffect creates another setInterval, and chaos ensued… You can delete the following example return and feel it
useEffect(() => {
console.log('use effect... ',count)
const timer = setInterval(() => setCount(count +1), 1000)
return ()=> clearInterval(timer)
})
Copy the code
😄6. UseEffect some rules for dark stamping:
1. The value of state used in useEffect is fixed in useEffect and will not be changed unless useEffect is refreshed
const [count, setCount] = useState(0)
useEffect(() => {
console.log('use effect... ',count)
const timer = setInterval(() => {
console.log('timer... count:', count)
setCount(count + 1)
}, 1000)
return ()=> clearInterval(timer)
},[])
Copy the code
2. UseEffect cannot be detected
const [count, setCount] = useState(0)
if(2 < 5){
useEffect(() => {
console.log('use effect... ',count)
const timer = setInterval(() => setCount(count +1), 1000)
return ()=> clearInterval(timer)
})
}
Copy the code
3. UseEffect cannot be interrupted
const [count, setCount] = useState(0)
useEffect(...)
returnUseEffect (...) }Copy the code
The specific reason has to do with the useEffect generation execution rule: read the documentation!
useRef
Why use useRef?
As mentioned earlier:
The value of state used in useEffect is fixed in useEffect and will not be changed unless useEffect refreshes and resets the value of state
const [count, setCount] = useState(0)
useEffect(() => {
console.log('use effect... ',count)
const timer = setInterval(() => {
console.log('timer... count:', count)
setCount(count + 1)
}, 1000)
return ()=> clearInterval(timer)
},[])
Copy the code
The useEffect state value is fixed, and the solution is to use the useRef function:
The global scope is modified in one place and updated everywhere else.
How to use useRef?
const countRef = useRef(0)
Copy the code
UseRef Knowledge points collection
😄 1. This is equivalent to the global scope, which is modified in one place and updated everywhere else…
const [count, setCount] = useState(0)
const countRef = useRef(0)
useEffect(() => {
console.log('use effect... ',count)
const timer = setInterval(() => {
console.log('timer... count:', countRef.current)
setCount(++countRef.current)
}, 1000)
return ()=> clearInterval(timer)
},[])
Copy the code
😄 2. Universal operation, used to manipulate the DOM
const btnRef = useRef(null)
click me
Remember to unbind events! return ()=> btnRef.current.removeEventListener(‘click’,onClick, false)
const Hook =()=>{
const [count, setCount] = useState(0)
const btnRef = useRef(null)
useEffect(() => {
console.log('use effect... ')
const onClick = ()=>{
setCount(count+1)
}
btnRef.current.addEventListener('click',onClick, false)
return ()=> btnRef.current.removeEventListener('click',onClick, false)
},[count])
return(
<div>
<div>
{count}
</div>
<button ref={btnRef}>click me </button>
</div>
)
}
Copy the code
useMemo
Why use useMemo?
An 🌰 :
const Child = memo(({data}) =>{
console.log('child render... ', data.name)
return (
<div>
<div>child</div>
<div>{data.name}</div>
</div>
);
})
const Hook =()=>{
console.log('Hook render... ')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
const data = {
name
}
return(
<div>
<div>
{count}
</div>
<button onClick={()=>setCount(count+1)}>update count </button>
<Child data={data}/>
</div>
)
}
Copy the code
When we click on the button to update count, the Effect component will render, and once render, this line of code will be executed:
const data = {
name
}
Copy the code
This line of code will generate an object with a new memory address, and then the memo’s Child component will be rerender, even though the value used by the Child will not change!
So redundant render, sensory performance wasted! So here comes useMemo as a transient capability.
How do I use useMemo?
const data = useMemo(()=>{
return {
name
}
},[name])
Copy the code
[name], useMemo, as a temporary storage, temporarily stores the last name result.
When we compare the last name, we find the name value has not changed! Data will not be reassigned to a new object this time!
Without a new object, there is no new memory address, and the Child will not be rerendered!
const Child = memo(({data}) =>{
console.log('child render... ', data.name)
return (
<div>
<div>child</div>
<div>{data.name}</div>
</div>
);
})
const Hook =()=>{
console.log('Hook render... ')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
const data = useMemo(()=>{
return {
name
}
},[name])
return(
<div>
<div>
{count}
</div>
<button onClick={()=>setCount(count+1)}>update count </button>
<Child data={data}/>
</div>
)
}
Copy the code
UseMemo Knowledge points collection
UseMemo has always had a memo.
😄 1. First, the memo is used as a PureComponent of a function component
However, if the function component is wrapped in react. Memo and its implementation has a Hook for useState or useContext, it will still re-render when the context changes.
😄 2. Also, the memo is shallow comparison, the object only compare memory address, as long as the memory address does not change, even if the value in your object changes will not trigger render
😄 3. Finally, what useMemo does, and here comes useMemo as a temporary storage capability:
useCallback
Why use useCallback?
UseMemo solves the problem of caching values, but what about functions?
When you click on the count button, the Effect component render is rendered:
const onChange=(e)=>{
setText(e.target.value)
}
Copy the code
The onChange function is regenerated and assigned to the Child component. The shallow comparison fails and the Child component successfully rerenders, even though the Child component did nothing!
const Child = memo(({data, onChange}) =>{
console.log('child render... ')
return (
<div>
<div>child</div>
<div>{data}</div>
<input type="text" onChange={onChange}/>
</div>
);
})
const Hook =()=>{
console.log('Hook render... ')
const [count, setCount] = useState(0)
const [name, setName] = useState('rose')
const [text, setText] = useState(' ')
const onChange=(e)=>{
setText(e.target.value)
}
return(
<div>
<div>count: {count}</div>
<div>text : {text}</div>
<button onClick={()=>setCount(count + 1)}>count + 1</button>
<Child data={name} onChange={onChange}/>
</div>
)
}
Copy the code
How do I use useCallback?
const onChange = useCallback((e)=>{
setText(e.target.value)
},[])
Copy the code
UseCallback knowledge point collection
😄1. UseMemo is similar to useCallback in that it serves as a cache. The essential difference may be:
UseMemo caches values
UseCallback is the cache function
😄2. No dependencies, add empty dependencies, that is, empty arrays!
useReducer
Why use useReducer?
As the name implies, the useReducer is the reducer in the class
How to use useReducer?
An 🌰 :
const reducer =(state = 0, {type})=>{
switch (type) {
case "add":
return state+1
case 'delete':
return state-1
default:
return state;
}
}
const Hook =()=>{
const [count, dispatch] = useReducer(reducer, 0)
return(
<div>
count:{count}
<button onClick={()=> dispatch({type:'add'})}>add</button>
<button onClick={()=> dispatch({type:'delete'})}>delete</button>
</div>
)
}
export default Hook
Copy the code
A collection of useReducer knowledge points
No special… 😼
useContext
Why use useContext?
UseContext is the context in the class.
How do I use useContext?
import React, {useContext, useReducer} from 'react'
const reducer = (state = 0, {type}) => {
switch (type) {
case "add":
return state + 1
case 'delete':
return state - 1
default:
return state;
}
}
const Context = React.createContext(null);
const Child = () => {
const [count, dispatch] = useContext(Context)
return( <div> <div>child... {count}</div> <button onClick={() => dispatch({type: 'add'})}>child add</button>
<button onClick={() => dispatch({type: 'delete'})}>child delete</button>
</div>
)
}
const Hook = () => {
const [count, dispatch] = useReducer(reducer, 10)
return (
<Context.Provider value={[count, dispatch]}>
<div>
<div>mom ... {count}</div>
<Child/>
<button onClick={() => dispatch({type: 'add'})}>mom add</button>
<button onClick={() => dispatch({type: 'delete'})}>mom delete</button>
</div>
</Context.Provider>
)
}
export default Hook
Copy the code
UseContext iS a collection of knowledge points
No special… 😼
Custom hook!
Define a custom hook that listens for window width and height when resize
import {useEffect, useState} from "react";
export const useWindowSize = () => {
const [width, setWidth] = useState()
const [height, setHeight] = useState()
useEffect(() => {
const {clientWidth, clientHeight} = document.documentElement
setWidth(clientWidth)
setHeight(clientHeight)
}, [])
useEffect(() => {
const handleWindowSize = () =>{
const {clientWidth, clientHeight} = document.documentElement
setWidth(clientWidth)
setHeight(clientHeight)
};
window.addEventListener('resize', handleWindowSize, false)
return () => {
window.removeEventListener('resize',handleWindowSize, false)}})return [width, height]
}
Copy the code
How to use:
const [width, height] = useWindowSize()
Copy the code