【react】react18的学习(三)--hooks组件

上一篇:【react】react18的学习(二)-三种组件

1、useState:使函数组件可以使用并修改 state
import { useState } from 'react'
const [num0, setNum0] = useState(10)
const [num0, setNum0] = useState(()=>{return 10})// 复杂初始化
setNum(1)
setNum(pre => {return pre + 1}) // 类组件的setState
  • 与类组件的setState()不同,不支持部分修改;所以推荐每个变量对应一个useState

  • 18中都是异步,多次fun会统一渲染;

  • 16版本中,也与setState一致,多次执行时,在合成事件、周期函数中是异步渲染(react处理),在其他异步操作中:如定时器、手动事件绑定等没有react干预是依次同步渲染;

  • 特别地,自带优化,当修改的值与之前的值一样时(Object.is),不重新渲染;

  • 如何实现循环渲染:fun的传参:

for (let i = 0; i < 10; i++) {
  setNum(pre => {
    return pre + 1
  })
}
// 类组件中setState循环
  state = {
    num: 0,
  }
  handle = () => {
    for (let i = 0; i < 10; i++) {
      this.setState(pre => {
        return { num: pre.num + 1 }
      })
    }
  }
2、useReducer:useState的升级版
  • 一般用于组件内状态比较多时,一般useState即可
// 普通组件A.jsx
import React, { useReducer } from 'react'
const initState = {
  num: 0,
}
const reducer = function (state, action) {
  state = { ...state }
  switch (action.type) {
    case 'plus':
      state.num++
      break
    case 'minus':
      state.num--
      break
  }
  return state
}
const A = () => {
  let [state, dispatch] = useReducer(reducer, initState)
  return (
    <div>
      <div>{state.num}</div>
      <button onClick={() => {dispatch({ type: 'plus' })}}>增加</button>
      <button onClick={() => {dispatch({ type: 'minus' })}}>减少</button>
    </div>
  )
}
export default A
3、useEffect:使函数组件可以使用 生命周期
import { useState, useEffect } from 'react' 
useEffect(() => {})// componentDidMount、componentDidUpdate
useEffect(() => {},[])// componentDidMount
useEffect(() => {},[num])// componentDidMount、num更新时相当于下一次渲染的更新后

useEffect(() => { return ()=>{}})// 上一次销毁前
useEffect(() => { return ()=>{}},[num]) // 更新num后,触发上一次销毁前

useLayoutEffect() // 同上,内部有状态更新时,会在浏览器绘制前更新组件,阻止本次页面绘制
  • 多个useEffect存放在effect链表中,等待视图挂载后依次执行;
4、useLayoutEffect
  • 用法与useEffect一样,都能获取到真实DOM对象;
  • 区别:比useEffect早一步执行,是在root.render()将虚拟dom解析出来真实dom对象后执行,此时浏览器还没有绘制,
  • useEffect:异步操作,与浏览器绘制渲染同时进行,官方更推荐使用;
  • useLayoutEffect:同步操作,在浏览器绘制渲染之前进行,内部如果更改状态,会阻止本次浏览器绘制,先去重新渲染组件再统一绘制;
5、useRef:使函数组件可以使用 ref
  • ref:用于获取标签元素、组件实例
  • 模仿类组件的两种方式:
// 函数方式
  let box
  useEffect(() => {
    console.log(box)
  }, [])
  return (
    <div ref={x => (box = x)}>
// React.createRef()方式
  let box = React.createRef()
  useEffect(() => {
    console.log(box.current)
  }, [])
  return (
    <div ref={box}>
  • 等价于React.createRef()方式
  let box = useRef(null)
  useEffect(() => {
    console.log(box.current)
  }, [])
  return (
    <div ref={box}>
  • 为什么还需要useRef

    每次更新组件,拿到的ref对象都是原来的,而React.createRef()每次执行都重新创建,这一点对类组件没影响,因为类组件每次渲染是执行的render()函数,不会重新执行React.createRef()

6、useImperativeHandle:获取hooks子组件状态
  • 获取hooks组件内状态
const Demo = React.forwardRef((props, ref) => {
  const [num, setNum] = useState(0);
  useImperativeHandle(ref, () => {
    return { num }// 这个对象将替掉返回的标签:{num:0}或{current:{num:0}}
  })
  • antd组件库中自有的获取form元素方式
// let form = useRef(null)
let [formIns] = Form.useForm()
----
<Form
  // ref={form} // form.current
  form={formIns} //直接:formIns
7、useMemo:性能优化hook1–计算缓存
let num = useMemo(()=>{return 2*y}) //不起缓存效果,每次组件更新都重新计算
let num = useMemo(()=>{return 2*y},[]) //一直使用缓存
let num = useMemo(()=>{return 2*y},[x,y,...]) //正确用法:状态x或y改变则重新计算
8、useCallback:性能优化hook2–方法缓存
  • 一般用于防止子组件做不必要的更新;

  • 子组件接收到这个num时,可以使用以下两种方式阻止自身做不必要的渲染:

    • 类子组件:继承class Demo extends PureComponent {render(){}}
    • hooks子组件:使用const Demo = React.memo(()=>{return ()})
const num = useCallback(()=>{}) //不起缓存效果,每次组件更新都重新创建函数
const num = useCallback(()=>{},[]) //一直使用缓存,内部变量始终为首次初始
const num = useCallback(()=>{},[y]) //正确用法:状态y改变则重新生成函数
9、自定义hooks:封装一些公共逻辑
  • 第一步:函数,use命名
  • 第二步:借助官方hooks,补充自定义逻辑;

下一篇:【react】react18的学习(四)-组件通信

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值