State 引入方式 1 import  React, {useState, useReducer} from  'react' 
 
useState声明方式 1 const  [state, setState] = useState(initialState);
 
useState返回后的第一个值将始终是更新后的最新的state
setState修改状态方法 1 2 3 4 5 6 7 8 9 10 11 function  Counter ({initialCount} )  {  const  [count, setCount] = useState(initialCount);   return  (     <>       Count: {count}       <button onClick={() => setCount(initialCount)}>Reset</button>        <button onClick={() => setCount(prevCount => prevCount - 1)}>-</ button>      <button onClick={() => setCount(prevCount  =>  prevCount + 1 )}>+</button>      </ >  ); } 
 
useReducer声明方式 1 const  [state, dispatch] = useReducer(reducer, initialArg, init);
 
e.g.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const  initialState = {count : 0 };function  reducer (state, action )  {  switch  (action.type) {     case  'increment' :       return  {count : state.count + 1 };     case  'decrement' :       return  {count : state.count - 1 };     default :       throw  new  Error ();   } } function  Counter ( )  {  const  [state, dispatch] = useReducer(reducer, initialState);   return  (     <>       Count: {state.count}       <button onClick={() => dispatch({type : 'decrement' })}>-</button>        <button onClick={() => dispatch({type: 'increment'})}>+</ button>    </>    ); } 
 
Effect useEffect 1 2 3 4 5 useEffect(()  => {     console .log('effect invoked' )     return  ()  =>  console .log('effect detected' ) }, [count] ); 
 
useLayoutEffect 
函数签名与useEffect相同 
会在任何state更新后,计算新DOM节点数,还未更新到真实DOM页面时执行 
执行顺序 
 
1 2 3 4 5 6 Layout effect invoked b_old.js:65 effect invoked b_old.js:74 layout effect detected b_old.js:73 Layout effect invoked b_old.js:66 effect detected b_old.js:65 effect invoked 
 
Context 
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language. 
 
React.createContext() && useContext() 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 const  themes = {  light: {     foreground: "#000000" ,     background: "#eeeeee"    },   dark: {     foreground: "#ffffff" ,     background: "#222222"    } }; const  ThemeContext = React.createContext(themes.light);function  App ( )  {  return  (     <ThemeContext.Provider value={themes.dark}>       <Toolbar />     </ThemeContext.Provider>    ); } function Toolbar(props) {   return (     <div>       <ThemedButton / >    </div>    ); } function ThemedButton() {   const theme = useContext(ThemeContext);   return (     <button style={{ background: theme.background, color: theme.foreground }}>       I am styled by theme context!     </ button>  ); } 
 
useRef 
获取某一个DOM节点,或组件的实例 
ref过去在functional component没有,因为无this,无法挂载 
返回同一个对象,不会生成新的对象 
 
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 function  MyCountFunc ( )  {         const  [count, dispatchCount] = useReducer(countReducer, 0 )     const  [name, setName] = useState('John' )          const  inputRef = useRef()     useEffect(() => {         console .log(inputRef)         return  ()  =>console .log('effect detected' )     }, [count])               useLayoutEffect(() => {         console .log('Layout effect invoked' )         return  ()  =>console .log('layout effect detected' )     }, [count])          return  (         <div>             <input ref={inputRef} value={name} onChange={(e)=>setName(e.target.value)}/>             <button onClick={()=>dispatchCount({type : 'add' })}>{count}</button>              <p>{Context}</ p>        </div>      ) } 
 
Hooks Render Optimization 
memo 
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 function  MyCountFunc ( )  {    const  [count, dispatchCount] = useReducer(countReducer, 0 );     const  [name, setName] = useState('John' )     const  countRef = useRef()     countRef.current = count     const  config = useMemo(() => ({             text: `count is ${count} ` ,             color: count>3 ? 'red' : 'blue'          })     , [count])     const  handleButtonClick = useCallback(()  =>  dispatchCount({type : 'add' }), [dispatchCount])     const  handleAlertButtonClick = function ( )  {         setTimeout(() => {             alert(countRef.current)         }, 2000 )     }     return  (         <div>             <input value={name} onChange={e=>setName(e.target.value)}/>             <Child                 config = {config}                 onButtonClick={handleButtonClick}             />             <button onClick={handleAlertButtonClick}>alert count</button>          </ div>    ) } const  Child = memo(    function  Child ( {onButtonClick, config} )  {         console .log('child render' );         return  (             <button onClick={onButtonClick} style={{color : config.color}}>                 {config.text}             </button>          )     } ) 
 
Closure Trap 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 function  MyCountFunc ( )  {    const  [count, dispatchCount] = useReducer(countReducer, 0 );     const  [name, setName] = useState('John' )     const  countRef = useRef()     countRef.current = count     const  config = useMemo(() => ({             text: `count is ${count} ` ,             color: count>3 ? 'red' : 'blue'          })     , [count])     const  handleButtonClick = useCallback(()  =>  dispatchCount({type : 'add' }), [dispatchCount])     const  handleAlertButtonClick = function ( )  {         setTimeout(() => {             alert(countRef.current)         }, 2000 )     }     return  (         <div>             <input value={name} onChange={e=>setName(e.target.value)}/>             <Child                 config = {config}                 onButtonClick={handleButtonClick}             />             <button onClick={handleAlertButtonClick}>alert count</button>          </ div>    ) } 
 
在调用setTimeout函数时,如果将count作为参数,则输出的是调用该函数时的count对象。如果想获取即时的值,则使用useRef