react-hooks
使得 function 组件具有 class 组件同等的”特效”(state, 生命周期函数…);
函数式开发;
useState
import React, {useState} from 'react';
function UseState() { const [name] = useState("tadm"); const [count, setCount] = useState(0);
return <div> <p>This is useState by {name}</p> <p>You clicked {count} times</p> // key2 <button onClick={()=>{ setCount(count+1) }}>click me</button> </div> } export default UseState;
|
useEffect
替代生命周期函数:componentDidMount componentDidUpdate componentWillUnmount
可进行副作用操作(网络请求等)
import React, {useState,useEffect} from 'react';
function UseEffect() { const [name] = useState("tadm"); const [count,setCount] = useState(0);
useEffect(()=>{ console.log(`useEffect=>You clicked ${count} times`) return ()=>{ console.log("unmount"); } },[count]);
return <div> <p>This is useEffect by {name}</p> <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>click me</button> </div> }
export default UseEffect;
|
useLayoutEffect
类似 ·useEffect·,不过 useEffect
是渲染后更新数据,不阻塞 DOM 更新;
而 useLayoutEffect
则会在内容更新到 DOM 上前运行,会阻塞 DOM 更新;
import React, {useEffect, useLayoutEffect, useState} from 'react';
function UseLayoutEffect(props) { const [count, setCount] = useState(1);
useLayoutEffect(()=>{ console.log("dosth") if(count === 0){ setCount(Math.random() * 100) } },[count]);
return ( <div> <h2>当前数字:{count}</h2> <button onClick={e => setCount(0)}>click</button> </div> ); }
export default UseLayoutEffect;
|
useContext
import React, {useState,createContext,useContext} from 'react';
const countContext = createContext();
function Counter(){ const obj = useContext(countContext); return (<h3>{obj.name} --- {obj.count}</h3>); }
function UseContext() { const [name] = useState("tadm"); const [count,setCount] = useState(0);
return <div> <p>This is UseContext by {name}</p> <p>You clicked {count} times</p> <button onClick={()=>{setCount(count+1)}}>click me</button> // key3 <countContext.Provider value={{name,count}}> <Counter/> </countContext.Provider> </div> }
export default UseContext;
|
其实也可以直接传入 props,个人感觉更方便。
useReducer & useMemo
useReducer — 替换 useState 来处理逻辑复杂操作;
useMemo — 性能优化(依赖项变化时才进行重新计算 — 缓存值)
import React, {useReducer,useEffect,useMemo} from "react";
const reducer = (state, action) => { switch (action) { case 'change': return state = "tadm1" case 'add': return state + 1 case 'sub': return state - 1 default: return state } }
function UseReducer() { const [name, dispatch1] = useReducer(reducer, "tadm", undefined); const [count, dispatch2] = useReducer(reducer, 0, undefined);
function getName() { console.log('getName触发') return name }
useEffect(() => { console.log('name effect 触发') }, [name])
useEffect(() => { console.log('count effect 触发') }, [count])
const memo_name = useMemo(() => { console.log('name memo 触发') return name + "---memo" }, [name])
return ( <div> <h2>The name is {getName()}</h2> <h2>memo name {memo_name}</h2> <h2>The count is {count}</h2> // key4 // click triggle getName, memo_name <button onClick={() => dispatch1('change')}>change</button> <button onClick={() => dispatch2('add')}>Increment</button> <button onClick={() => dispatch2('sub')}>Decrement</button> </div> ) }
export default UseReducer;
|
useCallback
同 useMemo
类似,只是返回的是缓存的函数。
import React, {memo, useState, useCallback, useEffect} from 'react';
function UseCallback() { const [count, setCount] = useState(1); const [val, setVal] = useState('');
const callback = useCallback(() => { console.log("do useCallback") return count; }, [count]);
return <div> <h4> {count}</h4> <h4> {val}</h4> <Child callback={callback}/> <div> <button onClick={() => setCount(count + 1)}> +</button> <input value={val} onChange={event => setVal(event.target.value)}/> </div> </div>; }
const Child = memo(({callback}) => { const [count, setCount] = useState(() => callback());
useEffect(() => { setCount(callback()); }, [callback]);
return <div> {count}</div> })
export default UseCallback;
|
useRef
获取 DOM 对象;
获取上一次状态值;
import React, {useState, useEffect, useMemo, useRef} from 'react';
function UseRef(props) { const [count, setCount] = useState(0);
const doubleCount = useMemo(() => { return 2 * count; }, [count]);
const counterRef = useRef();
useEffect(() => { counterRef.current = count; }, [count]);
return ( <> <div>上一次的值:{counterRef.current}</div> <button ref={counterRef} onClick={() => { setCount(count + 1) }}>Count: {count}, double: {doubleCount}</button> </> ); }
export default UseRef;
|