React 之 hook


hook简介

  • hook 是React 16.8 的新特性,使函数组件更强大
  • 优点
    1. 可以在不编写 class 的情况下使用 state 以及其他的 React 特性
    2. 解决业务逻辑难拆分的问题
    3. 方便状态逻辑复用
  • 注意点
    1. hook和class写法共存
    2. hook只能在函数组件中使用

基础hook

useState

  1. 为函数组件提供数据状态(state)

  2. const [count,setCount] = useState(0)
    count:使用的数据
    setCount:修改数据的对应方法
    
  3. 注意点

    1. useState的初始参数只会在组件首次渲染时使用,再次更新时会被忽略

    2. 每次通过 setCount 修改状态都会引起组件重新渲染

    3. useState 可以调用多次,每次都是独立的

    4. useState 不可以在函数组件之外的地方执行

    5. 如果初始值需要计算才能得到,那可以使用回调函数写法

      • const [count,setCount] = useState(()=>0)
        

useEffect

  1. 作用

    1. 发送网络请求
    2. localstorage 操作
    3. 监听数据修改 UI
    4. 手动修改DOM
  2. 执行时机

    1. 默认状态:首次执行+每次组件更新时执行
    2. 添加空数组([]) : 首次执行
    3. 添加需要监听的数据: 首次执行+监听数据变化时执行
  3. 清除副作用 :数据渲染 UI之外的操作

    1. useEffect(()=>{
          return()=>{
              //清理副作用
              //例如:清除定时器等
          }
      })
      

useContext

  1. 作用:在 hook 下跨组件传递数据
  2. 实现步骤
    1. 使用 createContext 创建 Context 对象
    2. 在顶层组件通过 Provider 提供数据
    3. 在底层组件通过 useContext 函数获取数据

额外的 hook

useRef

  1. 作用:获取真实的 DOM或者组件实例对象

  2. 实现步骤

    1. 导入useRef函数

    2. 执行 useRef 函数并传入 null,返回值为一个对象,内部有一个current属性存放 DOM对象(组件实例)

    3. 通过 ref 绑定获取元素或者组件

      1. const divRef = useRef()
        <div ref={divRef}></div>
        

useImperativeHandle

  1. 作用:在使用ref时自定义暴露父组件的实例值

  2. 实现步骤

    1. 给子组件绑定 useRef 属性
    2. 在子组件中导入 forwardRef ,包裹子页面顶层组件;包裹后第一个参数是props属性,第二个参数是ref属性
    3. 导入 useImperativeHandle ,有三个参数
      1. 第一个参数:ref
      2. 第二个参数: 返回值;需要在父页面操作的dom,
      3. 第三个参数:数组依赖项;控制 useImperativeHandle 返回值是否刷新
    4. 补充:
      1. 导入useImperativeHandle后可以通过返回控制子组件的全部ref;
      2. useImperativeHandle,返回值可以返回多种类型
      3. forwardRef ,只能控制一个
  3. 代码实现

    1. //父页面
      import {useRef} from "react"
      import ImperaciveHandle from "@/components/hooks/ImperativeHandle.jsx"
      
      const App()=>{
          const fatherRef = useRef()
          
          return (
          <div>
              // 操作子组件实例
              <button onClick={()=> {
                    fatherRef.current.userRef.current.focus()
                  }}>聚焦输入框</button>
                      <button onClick={()=> {
                fatherRef.current.passwordRef.current.focus()
                  }}>聚焦密码</button>
                  <ImperaciveHandle  ref={fatherRef}/> 
             </div>
          )
      }
      export default App;
      
      
    2. // 子组件
      import { useRef, forwardRef ,useImperativeHandle} from "react"
      // 1. 使用 forwardRef ,包裹页面组件,包裹后组件参数,第一个是props,第二个是ref
      
      const ImperaciveHandle = ({},ref) => {
          const userRef = useRef()
          const passwordRef = useRef()
      
          // 2.将需要父组件操控的dom,通过 useImperativeHandle 返回
          useImperativeHandle(ref,()=>{
              // 这里可以返回数组,对象,字符串,jsx等
              return {
                  userRef,
                  passwordRef,
              }
          //[]:依赖项控制 useImperativeHandle 返回值是否刷新
          },[])
      
          return (
              <div>
                  <input type="text" placeholder="用户名" ref={userRef} />
                  <input type="password" placeholder="密码" ref={passwordRef} />
              </div>
          )
      }
      export default forwardRef(ImperaciveHandle)
      
    3. 以上通过 useImperativeHandle 实现焦点控制

useMemo

  1. 作用:监听子组件变化来处理事件,优化子组件渲染

  2. useMemo 有两个参数,

1. 第一个参数是函数;
2. 第二个参数是数组,用来监听某个状态不改变,状态不改变,函数就不会执行,除了首次渲染时
  1.  import React, { useState, useMemo } from 'react';
    
    
const Child = ({ age, name, children }) => {
    //在不用useMemo做处理的时候,只要父组件状态改变了,子组件都会渲染一次;
    //用了useMemo可以监听某个状态name,当name变化时候执行useMemo里第一个函数,
    console.log('子组件渲染');
  
	function namechange() {
		console.log('子组件内部函数');
		return name + 'change';
	  }
	   
	  //useMemo有两个参数,和useEffect一样,第一个参数是函数,第二个参数是个数组,用来监听某个状态不变化
	const changedname = useMemo(() => namechange(), [ name ]);
	return (
		<div style={{ border: '1px solid' }}>
			<p>children:{children}</p>
			<p>name:{name}</p>
	           <p>age:{age}</p>
			<br />
	      	 {/* 子组件函数     */}  
	          <p>changed:{changedname}</p>
		</div>
	);
};
const UseMemo = () => {
	const [ name, setName ] = useState('张三'); 
	const [ age, setage ] = useState(20);
	return (
		<div>
			<button
				onClick={() => {
					setname('张三' + new Date().getTime()); 
				}}
			>name</button>
			<button
				onClick={() => {
					setage('年龄' + new Date().getTime());
				}}
			>age</button>
			<p>父组件的:{name}--{age}</p>
			<Child age={age} name={name}>
				{name}的children
			</Child>
		</div>
	);
};

```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值