The React zh-hans.reactjs.org/docs/hooks- Hooks Chinese website…
React Hooks
Built-in Hook | describe |
---|---|
useState | Maintaining state |
useEffect | Complete side effects |
useContext | Using shared State |
useReducer | An alternative to useState, similar to Redux |
useCallback | Caching functions and their references |
useMemo | Caching functions and their values |
useRef | Access to the DOM |
useImperativeHandle | Use the values and methods exposed by the child component |
useLayoutEffect | Completes the side effect operation. Unlike useEffect, this hook blocks the browser drawing |
useState
Add internal state to the React function component
import React, { useState } from 'react';
export default() = > {const [count, setCount] = useState(0);
return (
<>
<h1>count: {count}</h1>{/* Common update */}<button onClick={()= >setCount(count + 1)}>add</button>{/* Functional update */}<button onClick={()= >setCount(prevCount => prevCount + 1)}>add</button>
</>
);
};
Copy the code
useEffect
If you’re familiar with React Class lifecycle functions, you can think of useEffect Hook as componentDidMount, ComponentDidUpdate and componentWillUnmount.
import React, { useState, useEffect } from 'react';
export default() = > {const [count, setCount] = useState(0);
useEffect(() = >{
console.log('useEffect executes: componentDidMount');
}, [])
useEffect(() = >{
console.log('useEffect executes: componentDidUpdate');
}, [count])
useEffect(() = >{
return () = >{
console.log('useEffect executes: componentWillUnmount'); }}, [])return (
<>
<h1>count: {count}</h1>
<button onClick={()= >setCount(count + 1)}>add</button>
</>
);
};
Copy the code
useContext
Context provides a way to share values between components without explicitly passing props layer by layer through the component tree
import React, { useContext } from 'react';
const data = {
name: 'falco'.age: '18'
}
const ComponentContext = React.createContext(data);
const Child = () = > {
const { name, age } = useContext(ComponentContext);
return (
<div>
{name} - {age}
</div>)}const Parent = () = > {
return (
<>
<ComponentContext.Provider value={data}>
<Child/>
</ComponentContext.Provider>
</>)}export default Parent;
Copy the code
useReducer
Is an alternative to useState. Receive a Reducer of the form (state, action) => newState and return the current state and its matching dispatch method
import React, { useReducer } from 'react';
const initialState = [
{ id: 1.name: 'Joe' },
{ id: 2.name: 'bill'},]const reducer = (state, action) = > {
const { type, payload } = action;
switch(type){
case 'add':
return [...state, payload];
case 'update':
return state.map(item= >item.id === payload.id ? {... item, ... payload } : item);case 'remove':
return state.filter(item= >item.id ! == payload.id);case 'clear':
return []
default:
throw new Error()}}export default() = > {const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
List: {JSON.stringify(state)}
<div>
<button onClick={()= >Dispatch ({type: 'add', content: {id: 3, name: 'Cathy'}})} > add</button>
<button onClick={()= >Dispatch ({type: 'update', payload: {id: 3, name: 'x6'}})}>update</button>
<button onClick={()= >dispatch({type: 'remove', payload: { id: 1 }})}>remove</button>
<button onClick={()= >dispatch({type: 'clear', payload: { id: 1 }})}>clear</button>
</div>
</>)}Copy the code
useCallback
Both useCallback and useMemo can cache a reference or value to a function, but in a more subtle sense useCallback caches a reference to a function, useMemo caches the value of calculated data
import React, {
useState,
useRef,
useEffect,
useCallback
} from 'react';
const usePrevProps = value= > {
const ref = useRef(null)
useEffect(() = >{
ref.current = value
}, [])
return ref.current
}
const Button = React.memo(({ title, onClick }) = > {
console.log('render button');
return <button onClick={onClick}>{title}</button>;
});
export default() = > {const [count, setCount] = useState(0);
const [total, setTotal] = useState(0);
// const handleCount = () => setCount(count + 1);
const handleCount = useCallback(() = > setCount(count + 1), [])
const handleTotal = () = > setTotal(total + 1);
const prevHandleCount = usePrevProps(handleCount);
console.log('Are the two handlers equal:', prevHandleCount === handleCount); // true
return (
<div>
<div>Count is {count}</div>
<div>Total is {total}</div>
<br />
<div>
<Button title={'add Count'} onClick={handleCount} />
<Button title={'add Total'} onClick={handleTotal} />
</div>
</div>)}Copy the code
useMemo
You pass in the create function and the dependency array as arguments to useMemo, which recalculates memoized values only when a dependency changes. This optimization helps avoid costly calculations every time you render. If the dependency array is not provided, useMemo evaluates the new value each time it renders.
import React, {
useState,
useRef,
useEffect,
useCallback,
useMemo
} from 'react';
const usePrevProps = value= > {
const ref = useRef(null)
useEffect(() = >{
ref.current = value
}, [])
return ref.current
}
export default() = > {const [count, setCount] = useState(0);
const [total, setTotal] = useState(0);
UseMemo's first function is executed when the count variable changes
const calcValue = useMemo(() = >{
return Array(100000)
.fill(' ')
.map(v= > v);
}, [count])
const handleCount = () = > setCount(count + 1);
const handleTotal = () = > setTotal(total + 1);
const prevCalcValue = usePrevProps(calcValue);
console.log('Are the two calculations equal:', prevCalcValue === calcValue); // false
return (
<div>
<div>Count is {count}</div>
<div>Total is {total}</div>
<br />
<div>
<button onClick={handleCount}>Increment Count</button>
<button onClick={handleTotal}>Increment Total</button>
</div>
</div>)}Copy the code
useRef
UseRef returns a mutable ref object whose.current property is initialized as the passed parameter (initialValue). The ref object returned remains constant throughout the life of the component.
import React, { useRef } from 'react';
export default() = > {const inputEl = useRef(null);
const handleFocus = () = > {
// 'current' points to the text input element mounted to the DOM
inputEl.current.focus();
}
return (
<>
<input ref={inputEl} />
<button onClick={handleFocus}>Focus</button>
</>)}Copy the code
useImperativeHandle
You can have the parent component call properties/methods exposed by the child component. UseImperativeHandle should be used together with the forwardRef
import React, {
useState,
useRef,
forwardRef,
useImperativeHandle
} from 'react';
const Child = forwardRef((props, ref) = > {
const inputRef = useRef(null);
const [value, setValue] = useState(0);
useImperativeHandle(ref, () = >({
focus: () = > {
inputRef.current.focus()
},
setValue
}))
return (
<>
<div>child-value: {value}</div>
<input ref={inputRef}/>
</>)})export default() = > {const inputEl = useRef(null);
const handleFocus = () = > {
inputEl.current.focus();
}
const handleAdd = () = > {
inputEl.current.setValue(val= > val + 1)}return (
<>
<Child ref={inputEl} />
<button onClick={handleFocus}>Focus</button>
<button onClick={handleAdd}>add</button>
</>)}Copy the code
useLayoutEffect
Effect is called synchronously after all DOM changes. You can use it to read DOM layouts and trigger rerenders synchronously. The update schedule inside useLayoutEffect is flushed synchronously before the browser executes the drawing, which means it blocks the browser drawing. UseEffect whenever possible to avoid blocking visual updates.
import React, {
useState,
useRef,
useEffect,
useLayoutEffect
} from 'react';
const UseEffect = () = > {
const box = useRef(null);
useEffect(() = >{
box.current.style.backgroundColor = 'green';
}, [])
return (
<div
ref={box}
style={{
width: 200.height: 200.backgroundColor: 'red'}} >
UseEffect
</div>)}const UseLayoutEffect = () = > {
const box = useRef(null);
useLayoutEffect(() = >{
box.current.style.backgroundColor = 'green';
}, [])
return (
<div
ref={box}
style={{
width: 200.height: 200.backgroundColor: 'pink'}} >
UseLayoutEffect
</div>)}export default() = > {const [visible, setVisible] = useState(false);
return (
<div className='App'>
<button onClick={()= >setVisible(! Visible)}> Mount/unmount components</button>
{
visible && (
<div style={{ display: 'flex' }}>
<UseEffect />
<UseLayoutEffect />
</div>)}</div>)}Copy the code