React Hooks学习总结-01

1. 为什么使用HOOKS?

让函数式组件具有类组件的能力

2. 以下通过一个页面计时器的方法来介绍hook api

1. 先使用原来类组件的方式编写

import Reactl from 'react'
class MyCount extends React.Component {
    state = {
        count: 0
    }
    componentDidMount() {
        this.interval = setInterval(() => {
            this.setState({ count: this.state.count + 1 })
        }, 1000);
    };
    componentwillUnmount() {
        if (this.interval) { clearInterval(this.interval) }
    }
    render() {
        return <span>{this.state.count}</span>
    }
}
export default MyCount;

2. useState 和 useEffects(后面详细介绍)

const [count, setCount] = useState(0)

通过useState 可以让函数组件拥有类组价的 state
因为 函数式组件没有钩子函数 就需要用到useEffect
使用 hooks 改造如下

import React, {useState, useEffect} from 'react'
function MyCountFunc() {
    const [count, setCount] = useState(0)
    // hooks没有钩子函数概念 所以引入 useEffect
    useEffect(() => {
        const interval = setInterval(() => {
           // setCount(count + 1) // 不会实现更新数据
           setCount((count) => count + 1 )
        }, 1000);
        return () => clearInterval(interval); // 卸载的时候会执行
    })
    return <span>{count}</span>
}
export default MyCountFunc;

通过useState 生命完成后 会返回一个数组
const [count, setCount] = useState(0) // [a, b]
useState 中的默认值 只会在页面进来的时候加载第一次使用
在修改 useState 中的数据时 有两种放肆

  • 1、直接传入值进行修改 setCount(1)
  • 2、 传入一个callBack 并且要有返回值 setCount(© => c+1 )
    以上两个方法都可进行修 useState 中声明的值,但是:
    方法1:是不基于最新的count 来更新
    方法2:通过回调函数的方式 是可以基于当前值来更新数据的 可以避免数据不更新问题

3. useReducer

const [count, dispatchCount] = useReducer(countReducer, 0)

countReducer() 接收两个参数 1、传入的countReducer 函数 2、默认值

import React, { useReducer, useEffect } from 'react';
const countReducer = (state, action) => {
    switch (action.type) {
        case 'add':
            return state + 1;
        case 'minus':
            return state - 1;
        default:
           return state;
    }
}
const MyCountFunc = () => {
    const [count, dispatchCount] = useReducer(countReducer, 0)
    useEffect(() => {
        const interval = setInterval(() => {
            dispatchCount({type: 'minus'});
        }, 1000) 
        return () => clearInterval(interval)
    }, [])
    return (
        <div>
            counts: {count}
        </div>
    )
}
export default MyCountFunc;

4. useEffect

  • useEffect(() =>{return effect},[])
  • useEffect有两个参数, 第一个是调用函数, 第二个是监听值.
  • 调用函数 在组价加载完执行, return 出来的函数 是在组件卸载时执行
  • 第二个参数是一个数组,你可以理解为他是你所要监听的数据,数据变化了才会执行 useEffect
  • 如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount这三个函数的组合。
  • 第二个参数不传 相当于 componentDidUpdate
  • 第二个参数传入 [] 相当于componentDidMount
  • 第一个是调用函数 直接 return 出一个函数 叫销毁函数 相当于 componentWillUnmount
    以上只是模拟相等并不代表完全相等
import React, {useReducer, useState, useEffect } from 'react';
const countReducer = (state, action) => {
    switch (action.type) {
        case 'add':
            return state + 1;
        case 'minus':
            return state - 1;
        default:
           return state;
    }
}
const HooksUseEffect = () => {
    const [count, dispatchCount] = useReducer(countReducer, 0)
    const [name, setName] = useState('kings');
    useEffect(() => {
        console.log('useEffect')
        return () => console.log('useEffect calback')
    }, [count])
    return (
        <div> 
            <input value={name} onChange={(e) => {
                setName(e.target.value)
            }} />
            <button onClick={() => dispatchCount({type: 'add'})}>{count}</button>
        </div>
    )
}
export default HooksUseEffect;

5.useLayoutEffect

他和 useEffect 的区别就是,useEffect是等待Dom 节点加载完成后 再去执行。而useLayoutEffect 是在dom 加载完成之前执行,如果进行逻辑处理很多业务很麻烦的时候 他就会阻塞页面展示,一般不适用。

6. useContext

占位

7. useRef

import React, {useState, useEffect, useRef } from 'react';
const HooksUseEef = () => {
   const [name, setName] = useState('kings');
   const inputRef = useRef();
   useEffect(() => {
       console.log(inputRef.current.value)
       return () => console.log('useEffect calback')
   }, [name])
   return (
       <div> 
           <input ref={inputRef} value={name} onChange={(e) => {
               setName(e.target.value)
           }} />
       </div>
   )
}
export default HooksUseEef;

8、hooks 的优化 memo AND useMemo AND useCallback

在父组件调用子组件的时候,父组件数据更新了就会导致子组件重新渲染。可以使用memo 处理子组件,并且在父组件变化的数据使用useMemo(fun,[])来处理,useCallback(fun,[])来传入父组件操作的函数

import React, { useReducer, useState, useEffect, useMemo,memo, useCallback } from 'react';
const countReducer = (state, action) => {
    switch (action.type) {
        case 'add':
            return state + 1;
        case 'minus':
            return state - 1;
        default:
            return state;
    }
}
const MyCountFunc = () => {
    const [count, dispatchCount] = useReducer(countReducer, 0)
    const [name, setName] = useState('kings');
    // const config = {
    //     text: `count is ${count}`,
    //     color: count > 3 ? 'red' : 'blue'
    // }
    const config = useMemo(() => ({
        text: `count is ${count}`,
        color: count > 3 ? 'red' : 'blue'
    }), [count])
    // const handleClick = () => {
    //     dispatchCount({ type: 'add' })
    // }
    // const handleClick = useCallback(() => {
    //     return dispatchCount({ type: 'add' })
    // }, []);
    const handleClick = useMemo(() => () =>{ 
        dispatchCount({ type: 'add' });
    }, []);
    return (
        <div>
            <input value={name} onChange={(e) => {
                setName(e.target.value)
            }} />
            <Child
                config={config}
                onButtonClick={handleClick}
            />
        </div>
    )
};
const Child = memo(function Child({ onButtonClick, config }) {
    console.log('Child render')
    return (
        <button onClick={onButtonClick} style={{ color: config.color }}>
            {config.text}
        </button>
    )
});
export default MyCountFunc;

9、闭包陷阱

通过ref 可以避免

未完待续。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值