react 16.8新增 hook 浅谈

hook 是16.8新增的特性,他能让你在不使用class 组件的情况下也能用class组件的特性

下面就来简单讲讲几个常用的api吧

API:

首先我们通过React 引入对应的API

    import React, { useState } from 'react'

useState()

相当于创建一个state ,创建规则

      const  [ a, setA ] = useState();  //创建一个state对象

第一个 a 表示存储数据的参数,第二个setA 表示当要改变这个值时要执行的函数相当于 this.setState(),useState()里面可以传入一个函数,返回值为当前默认值:

       const  [ a, setA ] = useState(()=>1); //a的默认值为1

useEffect() 模拟class 的生命周期

第一个参数为函数

   const useEffect(()=>{
       //相当于componentDidMount()和componentDidUpdata() 
       console.log("componentDidMount执行了....");
       console.log("componentDidUpdata执行了....");

   },[]);
传入的函数返回一个函数 ,返回的函数相当于 componentWillUnmount()
   const useEffect(()=>{
       //相当于componentDidMount()和componentDidUpdata() 
       console.log("componentDidMount执行了....");
       console.log("componentDidUpdata执行了....");
       return ()=>{
           //执行销毁任务时触发
           console.log("componentWillUnmount执行了....");
       }
   },[]);

第二个参数为一个数组,

当数组没有值时默认全部useState的变量都触发第一个参数的函数

    //当数组中传入特定的useState设置的值时,
    //只有当遇到与之相对应的值变化时才开启执行第一个参数函数
   const useEffect(()=>{
       //相当于componentDidMount()和componentDidUpdata() 
       console.log("a被改变了....更新dom "); 
       return ()=>{
           //执行销毁任务时触发
           console.log("componentWillUnmount执行了....");
       }
   },[a]);//a不改变就不执行更新
利用这个特性我们可以过滤掉没有发生改变的state值不更新dom

useRef() 相当于 class 的 ref

    let ref=useRef();// 创建ref 
    return (
        {/*给dom元素赋值ref,这样我们就能获取ref */}
        <div ref={ref}>页面<div/>
    )
    //我们可以通过ref.current的值获取当前元素
我们可以通过useRef第一次的加载没有值的特性过滤掉第一次useEffect()的执行
  let ref=useRef();// 创建ref  
   const useEffect(()=>{
       if(!ref.current){//如果没有值,是第一次执行 ,直接过滤
          console.log('执行了componentDidWillmount.....')
          ref.current=true;
       }
       //相当于componentDidMount()和componentDidUpdata() 
       console.log("执行了componentDidUpdata..... "); 
       return ()=>{
           //执行销毁任务时触发
           console.log("componentWillUnmount执行了....");
       }
   }); 
我们通过useEffect()来模拟class的生命周期
  const [a, setA] = useState('a');
  const [b, setB] = useState('b');  
   //16.8之后新增。useRef是hook的功能
 
  useEffect(() => {
    console.log('componentDidMount.....');
  }, []);


  useEffect(() => {
    return ()=>{
      console.log('componentWillUnMount.....');
    }
  }, []); 
  const didmount = useRef();
  useEffect(()=>{
    if(!didmount.current)
      return;
    console.log('a didUpdate.........');
  }, [a]);

  useEffect(()=>{
    if(!didmount.current)
      return;
    console.log('b didUpdate.........');
  }, [b]);

  useEffect(() => {
    // 过滤第一次挂载
    if(!didmount.current){
      didmount.current = true;
      return;
    } 
    console.log('componentDidUpdate.........');
  });



  return (
    <div>
      <h1>two组件</h1>  
      <button onClick={()=>setA('aa')}>{a}</button>
      <button onClick={()=>setB('bb')}>{b}</button>
    </div>
  )

useCallback()

参数第一个为一个回调(钩子)函数

    const btnAction = useCallback(()=>{
        /* 我们可以通过回调函数传入子组件做一些事情 */
        console.log('执行了回调函数...')
    })
    return (
        <div>
         <Button btnAction={btnAction} />/* 将回调函数传入组件, */
        </div>
    )
useCallback包裹的函数,组件初始化时,创建一次,
之后的每一次更新,都获得上一次函数,不会重新声明函数
但是组件内部的依赖发生变化,上一次的函数就会释放,重新声明一个函数,所以如果函数内部触发了state的值的改变,就必须传入相应的值
    const [a,setA]=useState('a');
    const [b,setB]=useState('b');
    const btnAction = useCallback(()=>{
        console.log('执行了回调函数...')
        /* 使用了b的值,所以b值被缓存下来,
        如果下一次在调用,用的还是原来的b,
        如果b在外部发生了变化,则需要重新给新的b值 */
        setA(b)
    },[b])
    return (
        <div>
         <Button btnAction={btnAction} />/* 将回调函数传入组件, */
        </div>
    )

memo() 相当于class 的 PureComponent 过滤,没有改变的值就不刷新

 有两个参数:
 第一个参为一个组件,
 第二个参数相当于 class的shoudComponentupdata()

第一个参数为组件

    const Button = memo(( ) => { 
        return (
            <div>
                < button>按钮</button >
            </div>

            )
    })   
   
   export default Button

或者

function Button() { 
    return (
         <div>
            <button>按钮</button >
         </div> 
    )
}
 
export default memo(Button)

第二个参数 可以省略不写

    const Button = memo((props) => { 
        return (
            <div>  
                < button>按钮</button > 
            </div> 
        )
    },
    (oldProps, newProps) => {
            //接收两个参数,第一个是旧的props  第二个是新的props
            console.log(oldProps, newProps)
            //第二个函数表示 class 的should ComponentDidupdata()
            //自定义memo  false 表示一定更新 
            //如果为true  表示不更新。和class 的相反
            return true
        }
    ) 

useMemo()

组件内部的数据变化优化,没有触发改变的state数据就不重新执行计算代码
应用场景:首页轮播图请求一次之后,其他数据需要改变,会导致轮播图数据请求触发,我们可以通过useMemo()来过滤轮播图的数据请求代码

    const [a, setA] = useState(56)
    const [b, setB] = useState(44)
    const [show, setShow] = useState(false)
    console.log('组件渲染执行了'); 
    const btnAction = useCallback(() => {
        setShow(true) 
    }, [])

    const result = useMemo(() => {
        //求最大公约数
        var result = 1;
        for (var i = 1; i <= a && i <= b; i++) {
            console.log('进入了');
            if (a % i === 0 && b % i === 0) {
                result = i;
            }
        }
        return result
    }, [a, b])//如果依赖没有变化,就不更新,如果依赖发生改变,就重新计算
  
    return (
        <div>
            <p>{a}</p>
            <p>{b}</p>
            <p>最大公约数{result}</p>
            <button onClick={btnAction}>按钮</button>
            {show && <div 
             style={{ width: '100px',
             height: '100px', 
             background: 'red' }}>
             </div>}
        </div>
    )

useContext() 将Context简化使用

简洁使用 context 获取数据

    import React, { Component ,useContext} from 'react'
    import BorderContext from '../context/BorderContext'
    import ColorContext from '../context/ColorContext'

     //之前的使用
    // export default class Box extends Component { 
    //     render() {
    //         return (
    //             <BorderContext.Consumer >
    //                 {(border) => {
    //                     console.log(border);
    //                     return (
    //                         <ColorContext.Consumer>
    //                             {(color) => {
    //                                 return (<div style={{ border: border, color: color, width: '100px', height: '100px' }}>ewwe</div>)
    //                             }}
    //                         </ColorContext.Consumer>
    //                     )
    //                 }}
    //             </BorderContext.Consumer>
    //         )
    //     }
    // }

    // useContext()的使用

    import React, { Component, useContext } from 'react'
    import BorderContext from '../context/BorderContext'
    import ColorContext from '../context/ColorContext'

    export default function Box(params) { 
        const border = useContext(BorderContext)//获取所有的值
        const color = useContext(ColorContext) //获取所有的值
        return (<div style={{ border: border, color: color, width: '100px', height: '100px' }}>ewwe</div>) 
    } 

路由新增hook Api 简化使用history location match

    import { useHistory, useLocation, useRouteMatch, useParams } from "react-router-dom"

    export default function One(props) {
    const inputDOM = useRef();

    console.log(props);
    const history = useHistory();
    const location = useLocation();
    const match = useRouteMatch();
    const params = useParams();
    console.log(history, location, match, params)
    return (
        <div>
        <h1>one页面</h1>
        <input type="text" ref={inputDOM} />
        <button onClick={() => {
            if (inputDOM.current.value.length > 0) {
            //跳转页面
            props.history.push('/detail');
            } else {
            alert('输入不能为空');
            }
        }}>按钮</button>
        </div>
    )
    }

这些是我学习hook时留下的一些笔记,如果有错误,还望大神们指出!谢谢
具体内容请观看官网文档:
https://react.docschina.org/docs/hooks-intro.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值