r04函数组件 hook定义变量,修改数据、请求数据、清理定时器、跨组件传改值、获取dom(useState、useEffect、useContext、useRef、useLayoutEffect)

react18 之 04 函数组件 使用hook定义变量,修改数据等

  • 使用规则
    • 1:Hook不能在类组件中使用,只能在函数组件以及自定义Hook中使用
    • 2:只能在函数组件的最外层调用Hook,不能在循环、判断或子函数中调用Hook

react 函数组件 01:使用useState hook ( 类似state存储数据。eg:点击按钮,使得count自动+1)

  • 使用useState,可以在函数组件之中使用 state
import React, { useState } from 'react';

export default function UseState() {
    const [count, setCount] = useState(0)
    function countAdd() {
      let res = count + 1
      setCount(res)
    }
    return (
        <div className='content'>
          count - { count } <button onClick={countAdd}>count++</button>
        </div>
    )
}

react 函数组件 02:使用useEffect hook (组件的挂载、组件的更新、组件的卸载为一体)

  • React官方文档中,把数据获取、操作DOM、订阅数据、调用浏览器API等操作,称为副作用
  • 这个hook函数类似于(componentDidMount、componentDidUpdate 和 componentWillUnmount)也就是集成了组件的挂载、组件的更新、组件的卸载为一体
  • 这个hook函数,分为组件挂载时执行,组件视图更新执行,组件监测某个值或者某些值更新后执行
    • 1:组件挂载时执行 useEffect( () => {}, [] ) 就是后面传递了 [] 限制的
    • 1:组件挂载与卸载时执行 useEffect( () => { return ()=> {} }, [] ) 就是里面有 return ()=> {} 便是组件卸载的时候执行。可以清理副作用啥的
    • 2:组件视图更新执行 useEffect( () => {} )
    • 3:组件监测某个值或者某些值更新后执行 useEffect( () => {}, [timer] ) 就是后面传递了 [timer] 限制timer变化时才执行

useEffect 实现 组件挂载修改title和初始化时候调用接口拿数据

import React, { useEffect, useState } from 'react';

export default function UseEffect() {
    // 01:每次渲染后执行 - 只要页面有数据更新或者视图更新都会执行一次
    useEffect(() => {
      console.log('useEffect每次渲染后执行')
    })
    // 02:组件挂载的时候执行
    useEffect(() => {
        console.log('useEffect-组件挂载后执行')
        // 挂载的时候 修改title
        document.title = '我是UseEffect'
        // 使用 UseEffect 请求接口数据
        // listApi().then(res=>{
        //   console.log('res',res);
        // })
    }, []) // 注意点:默认需要传递空数组,否则会疯狂请求

    return (
        <div className='content'>
          UseEffect
        </div>
    )
}

在这里插入图片描述

useEffect 实现 组件卸载时 清除定时器

  • useEffect里面的 return ()=>{} 是组件卸载的时候执行
app.jsx
import React, { Component } from 'react';
import UseState from './useState';
export default class app extends Component {
 state = {
  isShowUseEffect: true
 }
 componentDidMount() {}
 closeUseEffect = () => {
  console.log('closeUseEffect');
  this.setState({
    isShowUseEffect: !this.state.isShowUseEffect
  })
 }
 render(){
  const { isShowUseEffect } = this.state
   return (
     <div>app
      isShowUseEffect - {isShowUseEffect}
      { isShowUseEffect ? <UseEffect ></UseEffect> : '' }
      <div><button onClick={this.closeUseEffect}>关闭UseEffect组件</button></div>
     </div>
   )
 }
}

useEffect.jsx
import React, { useEffect, useState } from 'react';

export default function UseEffect(props) {
    const [timer, setTimer] = useState(null)

    // 02: 使用useEffect 做一个定时器
    useEffect(()=>{
      const interval = setInterval(()=>{
        console.log('定时器执行');
        setTimer(timer+1)
      },1000)
      // return 这边就是清理副作用的 eg:组件卸载的时候 清除定时器 || 事件解绑、取消订阅
      return () => {
        clearInterval(interval)
      }
    },[timer]) // 传入timer 代表这个useEffect 只会对于这个timer变量变化的时候 触发

    return (
        <div className='content'>
          UseEffect
          timer - {timer}
        </div>
    )
}

效果

在这里插入图片描述

react 函数组件 03:使用useContext hook (访问上下文)

01:创建context上下文对象 LightContext.jsx

import { createContext } from 'react';
 // 创建一个上下文对象
export const LightContext = createContext();

02:UseContext.jsx 当前爷组件提供 light数据和提供修改light的方法

import React, { useState } from 'react';
import A from "./A";
import { LightContext } from "./LightContext";
export default function UseContext(props) {
    const [light,setLight] = useState({
        bg: '#fff',
        text: '白天'
    })
    return (
        // 使用 useContext创建的上下文 向下传递 light数据 和 修改light的方法setLight(可以同步修改light数据实现爷子孙组件渲染最新的light数据 )
        <LightContext.Provider value={{light,setLight}} >
            <div className='content'>
              UseContext的使用-{light.bg}
              <A></A>
            </div>
        </LightContext.Provider>

    )
}

03:A.jsx 在A组件修改 light数据,实现爷子孙 light数据同步更新

import React, { useContext } from 'react';
import ASon from "./ASon";
import { LightContext } from "./LightContext";
export default function A() {
  const { light, setLight } = useContext(LightContext);
  function changeLight() {
    setLight(prevLight => ({ ...prevLight, bg: 'red' }));
  }
    return (
        <div className='content'>
          A组件-light-{light.bg} <button onClick={changeLight}>A组件修改了light</button>
          <ASon></ASon>
        </div>
    )
}

04:ASon.jsx

import React, { useContext } from 'react';
import { LightContext } from "./LightContext";
export default function ASon(props) {
  const {light} = useContext(LightContext);
    return (
        <div className='content'>
          ASon组件 - { light.bg } - { light.text}
        </div>
    )
}

效果

在这里插入图片描述

react 函数组件 04:使用useRef hook (获取dom节点,实现input聚焦等)

code.jsx

import React, { useRef, useState } from 'react';

export default function UseRef(props) {
    const [name,setName] = useState('')
    const iptREf = useRef(null)
    function nameChange(event){
      setName(event.target.value)
    }
    function iptFocus(){
      iptREf && iptREf.current.focus()
    }
    return (
        <div className='content'>
          <input type='text' value={name} onChange={nameChange} ref={iptREf}></input>
           <div>
              <button onClick={iptFocus}>input自动聚焦</button>
          </div>
        </div>
    )
}

效果

在这里插入图片描述

react 函数组件 05:使用useLayoutEffect hook ( 副作用可用于初始化dom节点的宽高等=>echarts的宽高绘制等)

  • useLayoutEffect它非常类似于 useEffect,但是在组件完成更新后立即同步执行,而不是在浏览器绘制之后异步执行。
  • 作用:
    • 在 DOM 更新完成后立即同步执行副作用操作,它被调用时会在浏览器执行绘制之前触发,因此可以获取到最新的 DOM 布局信息。
  • 注意点:
    • 由于 useLayoutEffect 是同步执行的,因此需要注意它可能会阻塞主线程,导致性能问题

code.jsx 初始化时,拿到浏览器窗口的宽度与高度写入dom节点

import React, { useState,useLayoutEffect } from 'react';

export default function UseLayoutEffect(props) {
    const [size, setSize] = useState({width:0,height:0})
    useLayoutEffect(()=>{
      const handleResize = () => {
        setSize({width:window.innerWidth, height:window.innerHeight});
      };
      window.addEventListener('resize', handleResize);
      handleResize();

      // 清理副作用 卸载时候清理
      return () => window.removeEventListener('resize', handleResize);
    },[])

    return (
        <div className='content' style={{width:size.width,height:size.height,background:'#ccc'}}>
          useLayoutEffect - width - {size.width} - height-{size.height}
        </div>
    )
}

效果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值