只在 function 组件和自定义 hooks 中使用 hooks。
useState 返回数组的第二项以 set 开头(仅作为约定)。
自定义 hooks 以 use 开头(可被 lint 校验)。
useState:setState
useReducer:setState,同时 useState 也是该方法的封装
useRef: ref
useImperativeHandle: 给 ref 分配特定的属性
useContext: context,需配合 createContext 使用
useMemo: 可以对 setState 的优化
useCallback: useMemo 的变形,对函数进行优化
useEffect: 类似 componentDidMount/Update, componentWillUnmount,当效果为 componentDidMount/Update 时,总是在整个更新周期的最后(页面渲染完成后)才执行
useLayoutEffect: 用法与 useEffect 相同,区别在于该方法的回调会在数据更新完成后,页面渲染之前进行,该方法会阻碍页面的渲染
useDebugValue:用于在 React 开发者工具中显示自定义 hook 的标签
1.使用useState实现改变值
useState 有一个参数,该参数可传如任意类型的值或者返回任意类型值的函数。
useState 返回值为一个数组,数组的第一个参数为我们需要使用的 state,第二个参数为一个setter
函数,可传任意类型的变量,或者一个接收 state 旧值的函数,其返回值作为 state 新值。
在index.tsx中的代码如下:
import React, { useState } from 'react';
export default () => {
const [price, setPrice] = useState(0)
const [count, setCount] = useState(()=>{
const price = 5
return price;
})
return (
单价:{price}元
数量:{count}个
);
}
效果如图:通过setPrice和setCount改变price和count的值;
2.使用useContext传递值
设计目的: context 设计目的是为共享那些被认为对于一个组件树而言是“全局”的数据。
使用场景: context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。
注意点: 不要仅仅为了避免在几个层级下的组件传递 props 而使用 context,它是被用于在多个层级的多个组件需要访问相同数据的情景。
useContext该函数接收一个 Context 类型的参数(就是包裹了 Provider 那个对象),返回 Provider 中的 value 属性对象的值。
React 组件允许 Consumers 订阅 context 的改变
。而 Provider 就是发布这种状态的组件,该组件接收一个 value 属性
传递给 Provider 的后代 Consumers。一个 Provider 可以联系到多个 Consumers
。Providers 可以被嵌套以覆盖组件树内更深层次的值。
index.tsx:
import React, { useState, createContext } from 'react';
import Child from './index2';
export const CountText = createContext(4);
export default () => {
const [price, setPrice] = useState(0)
const [count, setCount] = useState(()=>{
const price = 5
return price
})
return (
单价:{price}元
数量:{count}个
);
}
index2.tsx:
import React, { useContext } from 'react';
import { CountText } from './index'
export default props => {
let count = useContext(CountText)
return (
这是从props拿到的单价:{props.Price}
这是从CountText拿到的数量:{count}
)
}
效果如下:除了useContext进行传值props依旧可以传值传回调。
3.useReducer使用方法
useState 的替代方案。它接收一个形如 (state, action) => newState 的 reducer,并返回当前的 state 以及与其配套的 dispatch 方法。
import React, { useReducer } from 'react';
export default function ReducerDemo() {
const [count, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'add':
return state + 1;
case 'sub':
return state - 1;
default:
return state;
}
}, 1)
function addNum() {
dispatch({
type: 'add'
})
}
function subNum() {
dispatch({
type: 'sub'
})
}
return (
现在的数值是{count}
)
}
同时,useReucer 也是 useState 的内部实现,useState 和 useReucer 的实现原理:
let memoizedState
function useReducer(reducer, initialArg, init) {
let initState = void 0
if (typeof init === 'function') {
initState = init(initialArg)
} else {
initState = initialArg
}
function dispatch(action) {
memoizedState = reducer(memoizedState, action)
}
memoizedState = memoizedState || initState
return [memoizedState, dispatch]
}
function useState(initState) {
return useReducer((oldState, newState) => {
if (typeof newState === 'function') {
return newState(oldState)
}
return newState
}, initState)
}
4.useEffect
useEffect方法接收传入两个参数:
注意:useEffect的第二个参数必须传空数组,这样它就等价于只在componentDidMount的时候执行。如果不传第二个参数的话,它就等价于componentDidMount和componentDidUpdate
useEffect(() => {
//每次render后执行
return () => {
//当前 effect 之前对上一个 effect 进行清除
}
})
useEffect(() => {
//仅在第一次render后执行
return () => {
//组件卸载前执行
}
}, [])
useEffect(() => {
//arr变化后,render后执行
return () => {
//下一useEffect运行前执行
}
}, arr)
回调返回值
useEffect
的第一个参数可以返回一个函数,当页面渲染了下一次更新的结果后,执行下一次useEffect
之前,会调用这个函数。这个函数常常用来对上一次调用useEffect
进行清理。
import React, { useState,useEffect } from 'react';
export default () => {
const [price, setPrice] = useState(0)
useEffect(() => {
console.log('执行...', price);
return () => {
console.log('清理...', price);
}
}, [price]);
return (
单价:{price}元
);
}
输出结果如图: useEffect
中返回的是一个函数,这形成了一个闭包,这能保证我们上一次执行函数存储的变量不被销毁和污染。
清除副作用
const [value, setValue] = useState()
useEffect(() => {
const timer1 = setTimeout(() => {
console.log('send')
console.log(value)
}, 2000)
return () => {
console.log('clearLastSend')
clearTimeout(timer1)
}
}, [value])
setValue(e.target.value)} />
5.使用useRef获取dom的ref
import React, { useRef } from 'react';
export default () => {
const inputRef = useRef(null);
const onButtonClick = () => {
console.log(inputRef.current.value)
};
return (
);
}