浅谈React

forwardRef和useImperativeHandle的联动使用

复制代码
import React, { useImperativeHandle, useRef } from "react"
import { forwardRef } from "react"

const CustomInput = forwardRef((props, ref) => {
    const inputRef = useRef<HTMLInputElement>(null)

    useImperativeHandle(ref, () => ({
        focus: () => {
            inputRef.current?.focus()
        }
    }))
    return <div>
        <input ref={inputRef} />
    </div>
})

export default CustomInput

巧用children

  • 一般用法

    父组件:

    import React from "react"
    import Child from './Child'

    const CustomInput = () => {
    return

    hello 靓仔


    }

    export default CustomInput

    子组件:

    import React from "react"

    const Child = ({
    children
    }) => {
    return

    {children}

    }

    export default Child

  • 函数用法

    父组件:

    import React from "react"
    import Child from './Child'

    const CustomInput = () => {
    return
    {(arr)=>


    {arr.map((v,idx)=>{
    return
    {v}

    })}
    }

    }

    export default CustomInput

    子组件:

    import React from "react"

    const Child = ({
    children
    }) => {
    const arr = [1,2,4,5]
    return

    {children(arr)}

    }

    export default Child

useEffect

  • 没有依赖,类似于componentDidMount和componentDidUpdate

    import React, { useEffect, useState } from "react"

    const Detail = () => {
    const [count, setCount] = useState(1)
    const [num,setNum] = useState(2)
    useEffect(()=>{
    console.log(count,'count',num,'num')
    })
    return


    <div onClick={() => setCount(count + 1)}>add count

    <div onClick={() => setNum(num + 1)}>add num

count: {count}

num: {num}


}

export default Detail

  • 依赖是个空数组,相当于componentDidMount

    import React, { useEffect, useState } from "react"

    const Detail = () => {
    const [count, setCount] = useState(1)
    const [num,setNum] = useState(2)
    useEffect(()=>{
    console.log(count,'count',num,'num')
    },[])
    return


    <div onClick={() => setCount(count + 1)}>add count

    <div onClick={() => setNum(num + 1)}>add num

count: {count}

num: {num}


}

export default Detail

  • 有依赖,componentDidMount和对应依赖的componentDidUpdate

    import React, { useEffect, useState } from "react"

    const Detail = () => {
    const [count, setCount] = useState(1)
    const [num,setNum] = useState(2)
    useEffect(()=>{
    console.log(count,'count',num,'num')
    },[num])
    return


    <div onClick={() => setCount(count + 1)}>add count

    <div onClick={() => setNum(num + 1)}>add num

count: {count}

num: {num}


}

export default Detail

useEffect和useLayoutEffect

useEffect在渲染后执行,而useLayouEffect是在渲染之前执行

最典型的例子就是实现一个tooltip组件,在性能比较差的情况下,useEffect会先渲染初始状态再更新,而useLayoutEffect会阻塞UI的更新即不会出现组件闪烁的情况~

阻塞代码:

复制代码
let now = performance.now();
while (performance.now() - now < 100) {
}

useEffect在性能差的情况下会出现以下效果

useContext

依赖注入

复制代码
父级:
export const ThemeContext = createContext({});
const App = ()=>{

return  <ThemeContext.Provider value={{name:"real hot"}}>
        ......
    </ThemeContext.Provider>
}

 子级:
  const context = useContext(ThemeContext)
  console.log(context)

useState的变动

在react管辖下(react17.x.x)

状态能够更改多次,只渲染一次

复制代码
const handleCount= ()=>{
  setCount(count=>count+1)
  setCount(count=>count+1)
}

多次更改状态会被合并成一次更改,即一次生效其他无效,只渲染一次

复制代码
const handleCount= ()=>{
  setCount(count+1)
  setCount(count+1)
}

在异步任务/原生事件下(react17.x.x)

复制代码
const handleCount= ()=>{
setTimeout(()=>{
  setCount(count=>count+1)
  setCount(count=>count+1)
})
}

版本的演变(React18)

react18之后在异步操作或者react事件中都是批量更新,即多个状态更新合成一次渲染,若需要多次渲染可使用flushsync

复制代码
const handleCount= ()=>{
  flushSync(()=>{
    setCount(count=>count+1)
  })
  flushSync(()=>{
    setCount(count=>count+1)
  })

}

探索生命周期函数

父子组件生命周期执行顺序

挂载:

更新:

卸载:

错误处理

生命周期方法:

getDerivedStateFromError

componentDidCatch

缺点(没办法捕获):

实现一个简单的Message

复制代码
import ReactDOM from 'react-dom';
import { Modal } from 'antd';
const ToastFn = () => {
let parent = null;
return {
open: function ({ el, container = document.body }) {
// this.destroy();
parent = document.createElement('div');
document.body.appendChild(parent);
ReactDOM.render(<Modal open onCancel={this.destroy}>{el}</Modal>, parent)
},
destroy: function () {
ReactDOM.unmountComponentAtNode(parent);
},
};
};
const Toast = ToastFn();
export default Toast;
上一篇:软件开发C#(Sharp)总结(续)
下一篇:【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第一篇 嵌入式Linux入门篇-第十九章 Linux 工具之make 工具和 makefile 文件
相关推荐
SendTomo10 小时前
P2P文件传输工具对比:SendTomo vs send.wang
javascript·网络协议·webrtc·html5·p2p
犹豫的果冻布丁11 小时前
从零给 DeepSeek Harness 写一个壁纸皮肤插件(已开源)
前端·后端
漏刻有时11 小时前
数据可视化Three.js 3D 地图实战:单文件原生实现省域区县拉伸建模
前端
会说话的番茄11 小时前
AI 满嘴跑火车怎么办?给它配个"小抄"
前端·aigc
计算机魔术师11 小时前
AI 权力集中辩论实录:从「token 工厂」到「唯一幸存者」
前端
eric-sjq12 小时前
WanlyFrontend 中文声明式前端语言完全指南:让 0.6B 模型写出漂亮网页
前端
Full Stack Developme12 小时前
跨站请求伪造 (CSRF) 是什么 设计及工作原理
前端·okhttp·csrf
SendTomo12 小时前
WebRTC文件互传工具实测对比
javascript·网络·webrtc·html5·p2p
MoSTChillax12 小时前
UI规范设计:从视觉到交互的全面指南
前端·ui·产品经理·设计规范·vibecoding
雪碧聊技术12 小时前
Vue + Element Plus 实现文本溢出显示省略号及悬浮提示
前端·javascript·css·vue.js·文本溢出省略
热门推荐
01GitHub 镜像站点02国内可直接用、免费额度/永久免费的大模型API清单(含 SiliconFlow、火山、阿里、智谱、百度、Kimi、DeepSeek、DMXAPI 等)03微信历史版本含下载地址( Windows PC | 安卓 | MAC )及设置微信不更新042026 国产 AI 大模型横评:DeepSeek、通义千问、Kimi、文心一言、星火、豆包谁更能打?05Agnes AI 免费 API 接入指南:文本、生图、生视频,一套接口全免费06历年考研数学一、数学二、数学三真题试卷及答案PDF07VSCode+CodeX扩展,无法启动08AI 编程 IDE 全景解析 2026:Agent 全面接管开发链路09如何新建文件夹? 电脑新建文件夹的4种方法102026年7月AI圈大地震:GPT-5.6被政府限制、Claude入驻Slack、Anthropic自研芯片