Reducer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import { useState } from "react" ;export default function App ( ) { const [count, setCount] = useState (0 ); const handleIncrement = ( ) => { setCount (count + 1 ); } const handleDecrement = ( ) => { setCount (count - 1 ); } return ( <div style ={{ padding: 10 }}> <button onClick ={handleIncrement} > +</button > <span > {count} </span > <button onClick ={handleDecrement} > -</button > </div > ); }
使用Reducer改造后
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import { useReducer } from "react" ;function countReducer (state, action ) { switch (action.type ) { case 'INCREMENT' : return state + 1 ; case 'DECREMENT' : return state - 1 ; default : return state; } }export default function App ( ) { const [state, dispatch] = useReducer (countReducer, 0 ); const handleIncrement = ( ) => dispatch ({ type : 'INCREMENT' }); const handleDecrement = ( ) => dispatch ({ type : 'DECREMENT' }); return ( <div style ={{ padding: 10 }}> <button onClick ={handleIncrement} > +</button > <span > {state} </span > <button onClick ={handleDecrement} > -</button > </div > ); }
useRef 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import React , { useRef } from 'react' ;export default function UseRefExample ( ) { const inputRef = useRef (null ); const focusInput = ( ) => { inputRef.current .focus (); }; return ( <div > <h2 > useRef Example</h2 > <input ref ={inputRef} placeholder ="Type something" /> <button onClick ={focusInput} > Focus the input</button > </div > ); }
Components 普通的Child组件,父组件不能直接访问到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import React , { useRef } from 'react' ;function Child ( ) { return ( <div > 子组件 </div > ) }export default function UseRefExample ( ) { const childRef = useRef () function handleClick ( ) { } return ( <div > <Child ref ={childRef} /> <button onClick ={handleClick} > 按钮</button > </div > ) }
修正后的代码 使用useImperativeHandle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import React , { forwardRef, useImperativeHandle, useRef } from 'react' ;const Child = forwardRef (function (props, ref ) { useImperativeHandle (ref, () => { return { handleClick ( ) { console .log ('子组件的方法' ) } } }) return ( <div > 子组件 </div > ) })export default function UseRefExample ( ) { const childRef = useRef () function handleClick ( ) { childRef.current .handleClick () } return ( <div > <Child ref ={childRef} /> <button onClick ={handleClick} > 按钮</button > </div > ) }
useEffect 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import React , { useState, useEffect } from 'react' ;export default function UseEffectExample ( ) { const [count, setCount] = useState (0 ); useEffect (() => { document .title = `You clicked ${count} times` ; return () => { document .title = 'React App' ; }; }, [count]); return ( <div > <h2 > useEffect Example</h2 > <p > You clicked {count} times</p > <button onClick ={() => setCount(count + 1)}> Click me </button > </div > ); }
useMemo 示例代码如下:
如果子组件需要进行一些复杂的运算, 在父组件发生变化的时候,子组件的输入没有变,但是也会触发重新渲染。 实际上,输入没有变,重复渲染计算是不必要的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import { useState } from "react" ;function DoSomeMath ({ value } ) { console .log ("DoSomeMath组件重新渲染了" ); let result = 0 ; for (let i = 0 ; i < 1000000 ; i++) { result += value * 2 ; } return ( <div > <p > 输入内容: {value}</p > <p > 经过复杂计算的数据: {result}</p > </div > ) }export default function App ( ) { const [inputValue, setInputValue] = useState (5 ); const [count, setCount] = useState (0 ); return ( <div > <p > count的值为: {count}</p > <button onClick ={() => setCount(count + 1)}>点击更新</button > <br /> <br /> <input type ="number" value ={inputValue} onChange ={(e) => setInputValue(e.target.value)} /> <DoSomeMath value ={inputValue} /> </div > ) }
useMemo(func, dep)
修改后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import { useState, useMemo } from "react" ;function DoSomeMath ({ value } ) { const result = useMemo (() => { console .log ("DoSomeMath组件重新渲染了" ); let result = 0 ; for (let i = 0 ; i < 1000000 ; i++) { result += value * 2 ; } return result; }, [value]); return ( <div > <p > 输入内容: {value}</p > <p > 经过复杂计算的数据: {result}</p > </div > ) }export default function App ( ) { const [inputValue, setInputValue] = useState (5 ); const [count, setCount] = useState (0 ); return ( <div > <p > count的值为: {count}</p > <button onClick ={() => setCount(count + 1)}>点击更新</button > <br /> <br /> <input type ="number" value ={inputValue} onChange ={(e) => setInputValue(e.target.value)} /> <DoSomeMath value ={inputValue} /> </div > ) }
useCallBack 与useMemo类似,useMemo记忆化的是数据, useCallback记忆化的是函数(函数式组件也是函数)。
父组件发生变化时,不想子组件重新渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import { useState } from "react" ;function Button ({ onClick } ) { console .log ('Button渲染了' ); return <button onClick ={onClick} > 子组件</button > }export default function App ( ) { const [count, setCount] = useState (0 ); const handleUpdate = ( ) => { setCount (count + 1 ); } const handleClick = ( ) => { console .log ('点击按钮' ); } return ( <div > <p > Count: {count}</p > <button onClick ={handleUpdate} > 更新</button > <br /> <Button onClick ={handleClick} > </Button > </div > ) }
修改代码
将Button组件 使用memo
将参数handleClick改成setCallback
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import { useState, memo, useCallback } from "react" ;const Button = memo (function ({ onClick } ) { console .log ('Button渲染了' ); return <button onClick ={onClick} > 子组件</button > })export default function App ( ) { const [count, setCount] = useState (0 ); const handleUpdate = ( ) => { setCount (count + 1 ); } const handleClick = useCallback (() => { console .log ('点击按钮' ); }, []) return ( <div > <p > Count: {count}</p > <button onClick ={handleUpdate} > 更新</button > <br /> <Button onClick ={handleClick} > </Button > </div > ) }