Hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
useState(保存组件状态)
const [count, setCount] = useState(0);
useEffect(处理副作用)和useLayoutEffect (同步执行副作用)
Function Component 不存在生命周期,所以不要把 Class Component 的生命周期概念搬过来试图对号入座。
useEffect(() => {
第一次加载时执行,依赖里的数据更新时执行
return () => {
页面销毁时执行 return 的函数
}
}, [依赖的数据;空数组,表示不依赖])
useEffect和useLayoutEffect有什么区别?
简单来说就是调用时机不同, useLayoutEffect 和原来 componentDidMount & componentDidUpdate 一致,在 react完成DOM更新后马上同步调用的代码,会阻塞页面渲染。而 useEffect 是会在整个页面渲染完才会调用的 代码。
官方建议优先使用 useEffect
useCallback(记忆函数)
- useCallback返回的是里面的整个个函数
- 当依赖的值发生变化,useCallback才会重新声明一次,
- 不变化就会从缓存中拿上一次值———防止没有值变化时,组件重新渲染,方法重新创建
- 第二个参数[] 存放依赖的值
var handleClick = useCallback(
()=>{
console.log(name)
},[name])
<button onClick={()=>handleClick()}>hello</button>
//只有name改变后, 这个函数才会重新声明一次,
//如果传入空数组, 那么就是第一次创建后就被缓存, 如果name后期改变了,拿到的还是老的name。
//如果不传第二个参数,每次都会重新声明一次,拿到的就是最新的name.
useMemo 记忆组件
- useMemo返回的是计算出来的结果,
- 只有依赖值改变的时候才会重新计算,
- 不改变就会拿上次缓存的结果——防止计算繁琐占有资源
- 第二个参数[] 存放依赖的值 useCallback 的功能完全可以由 useMemo 所取代,如果你想通过使用 useMemo 返回一个记忆函数也是完全可以的
useMemo(() => fn, [])
唯一的区别是:useCallback 不会执行第一个参数函数,而是将它返回给你,而 useMemo 会执行第一个函数并 且将函数执行结果返回给你。
useRef(保存引用值)
- 两个作用
- 绑定 dom/组件 上获得 dom/组件 对象
- 保存临时变量,不然其消失
const count = useRef(null);
useContext
接收一个 context 对象(React.createContext 的返回值)并返回该 context 的 value。由上层组件中距离当前组件最近的 <GlobalContext.Provider> 的 value prop 决定。
let GlobalContext = React.createContext();
export default function Father() {
return (
<GlobalContext.Provider value={{myname:'admin'}} >
<Child></Child>
</GlobalContext.Provider>
)
}
function Child() {
const value = useContext(GlobalContext)
return (
<div>Child---{value.myname}</div>
)
}
别忘记 useContext 的参数必须是 context 对象本身:
- 正确:
useContext(MyContext) - 错误:
useContext(MyContext.Consumer) - 错误:
useContext(MyContext.Provider)
useReducer
const [state, dispatch] = useReducer(reducer, initialState);
useState的替代方案。它接收一个形如(state, action) => newState的 reducer,并返回当前的 state 以及与其配套的dispatch方法。- 在某些场景下,
useReducer会比useState更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。
function reducer(prestate, action) {
switch (action.type) {
case 'add':
return {count: prestate.count + 1};
case 'sub':
return {count: prestate.count - 1};
default:
return prestate
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, {count: 0});
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'sub'})}>-</button>
<button onClick={() => dispatch({type: 'add'})}>+</button>
</>
);
}
自定义hook
当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。而组件和 Hook 都是函数,所以也同样适用这种方式。
自定义 Hook 是一个函数,其名称以 “use” 开头,函数内部可以调用其他的 Hook。