0.0

  • Hooks 是 react 在16.8.0版本新增的新语法
  • 可以让你在函数组件中使用 state 和其他的 react 特性
  • 用来在函数中钩入react的特性

    为什么用

  • 类组件很难复用状态逻辑

  • 复杂组件难以理解,尤其生命周期函数,有时还要两个生命周期函数中对照修改代码,甚至要写同样逻辑的代码
  • react组件一直都更像是函数,使用hook使得完全拥抱函数

    常用 Hook

    State Hook: useState()

    函数式组件中,this 为 undefined ,state 就更没有了。便可以通过这个 Hook 使用 state,使得函数组件也有可操作的状态
    语法
    const [state, setstate] = useState(initialState)
    在引入 react 时,就不用引入 Component,而是引入 useState 这个方法了
    state 是状态, setState 就是操作状态的那个方法了
    与组件那个控制状态的方法 也有区别:那个是合并更新,而这个是覆盖更新。
    setState ()2种写法:
  1. setState (newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
  2. setState (value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态

Effect Hook:useEffect()

用于模拟类组件中的生命周期钩子(副作用操作)

  • 例如
    • 异步操作:发ajax请求数据获取
    • 设置订阅 / 启动定时器
    • 手动更改真实DOM

可以在一个函数组件中设置多个 useEffect
语法

  1. useEffect(() => {
  2. effect // 在此可以执行任何带副作用操作
  3. return () => {// 在组件卸载前执行
  4. cleanup // 在此做一些收尾工作, 比如清除定时器/取消订阅等
  5. }
  6. }, [input])// 如果指定的是[], 回调函数只会在第一次render()后执行

可以视作以下三个钩子的集合 (其实这样理解不是特别好,但我刚开始学习的时候确实是这样理解的。)

  • componentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()

    异步操作

    如果是用 fetch ,可以直接操作。
    但是这里面不支持 直接使用await 、 async,但是也提供了解决方法 ```jsx const Index = ()=>{ useEffect(()=>{
    1. async function demo(){}
    demo() //直接调用该方法 }) return <></> } //或者将 async 方法放在useEffect 外面

async function demo(){}

const Index = ()=>{ useEffect(()=>{ demo() //直接调用该方法 }) return <></> }

  1. <a name="NWN35"></a>
  2. ### useLayoutEffect
  3. 和前者的区别就是,它是在所有的DOM渲染完毕之后**同步**执行 Effect,一般在这里面进行**DOM相关操作,**改变浏览器的一些显示效果
  4. <a name="Mc9x5"></a>
  5. ### useMemo
  6. 没用这个的时候,当一个组件中的一个属性被改变,那么整个组件——包括与改变的属性无关的部分——都会被重新渲染,就会影响性能。而用memo设置出来的属性相关的东西,就只会在该属性改变时才重新渲染
  7. ```jsx
  8. //函数组件内部:
  9. const [text,setText] = useState("aa")
  10. const memoText = useMemo(()=>{
  11. //console.log("memo")
  12. return text
  13. },[text])

很明显就是用来做性能优化,该函数返回的是一个经过缓存的值。

useCallback

也与缓存相关,主要用来缓存相关的函数

  1. const handleClickCount = useCallback(()=>{
  2. setCount(count+1)
  3. },[count])

Ref Hook: useRef()

语法

  1. const ref = useRef(initialValue)

其用法与类组件中的 ref 的 createRef() 相似


  • 主要作用是 让状态数据之间有更为紧密的关系,各个部分render时操作同一个唯一的值引用
  • 访问dom节点

    useReducer

    1. const [state, dispatch] = useReducer(
    2. reducer,
    3. initialState
    4. );

    同 redux 中的 reducer ,The reducer takes in the initialState and the action, so based on the action type, the reducer returns a new state object.
    reducer 是接收 state、action 两个参数,根据action.type 进行对应的操作,返回修改后的 state

    useContext

    1. const {state, dispatch} = useContext(UserContext)

    上面的UserContext 是与上一个 Hook 有关

    code

    现在我将各个 hook 与类组件中对应的东西横向比较,两段代码的页面效果是一样的。
    类组件版本

    1. class Demo extends Component {
    2. state = { count: 0 };
    3. myRef = React.createRef()
    4. add1 = () => {
    5. this.setState(state => ({ count: state.count + 1 }));
    6. };
    7. unmount = () => {
    8. ReactDom.unmountComponentAtNode(document.getElementById("root"));
    9. };
    10. show=()=>{
    11. alert(this.myRef.current.value)
    12. }
    13. componentDidMount() {
    14. this.timer = setInterval(() => {
    15. this.setState(state => ({ count: state.count + 1 }));
    16. }, 500);
    17. }
    18. componentWillUnmount() {
    19. clearInterval(this.timer);
    20. }
    21. render() {
    22. return (
    23. <div>
    24. <input type="text" ref={this.myRef}/>
    25. <h1>现在求和为{this.state.count}</h1>
    26. <button onClick={this.add1}>点我加1</button>
    27. <button onClick={this.unmount}>卸载组件</button>
    28. <button onClick={this.show}>点击提示数据</button>
    29. </div>
    30. );
    31. }

    函数组件版本

    1. function Demo() {
    2. const [count, setCount] = React.useState(0);
    3. const myRef = React.useRef()
    4. React.useEffect(() => {
    5. const timer = setInterval(() => {
    6. setCount(count => count + 1);
    7. }, 500)
    8. return ()=>{
    9. clearInterval(timer)
    10. }
    11. }, []);
    12. function add1() {
    13. // setCount(count + 1);
    14. setCount(count => count + 1);
    15. }
    16. function unmount() {
    17. ReactDom.unmountComponentAtNode(document.getElementById("root"));
    18. }
    19. function show(){
    20. alert(myRef.current.value)
    21. }
    22. return (
    23. <div>
    24. <input type="text" ref={myRef} />
    25. <h1>现在求和为{count}</h1>
    26. <button onClick={add1}>点我加1</button>
    27. <button onClick={unmount}>卸载组件</button>
    28. <button onClick={show}>点击提示数据</button>
    29. </div>
    30. );
    31. }

    自定义hook

    注意:必须用 use 开头

    总结

  • 没有this导致class中很多东西没有

  • 没有生命周期钩子
  • 但都有别的方法完成
  • 看明白code就可以了

注意:

  • 只在最顶层使用hook
  • 只在react函数中调用hook