«

笔记-16-React

codeez 发布于 阅读:59 笔记


react18最大变化就是性能提升


jsx比普通html更严格,在jsx中写class的话要用className

父传子


父给子传方法,子事件触发这个方法
使用useState改变值的时候 整个组件会重新执行一遍。
useState改变对象里的值,需要改变这个对象的地址。

npm install -S use-immer 


替换useState,如果再修改data【只读】就会报错
用Immer的时候 修改值这样写,draft是草稿的意思

组件在页面上被销毁,状态会被清空,组件所处的UI节点位置发生变化时,组件会被销毁。
当存在Key值时 不管UI节点是否发生变化,只要Key变了,组件就被销毁。

Reducer聚合数据处理
import { useReducer } from "react"

function listReducer(state, action){
    if(action.type === 'add'){
        const newData = [...state, action.value]
        return newData    
    }
    if(action.type === 'del'){
        const newData = [...state]
        newData.splice(index,1)
        return newData    
    }
    return state
}

const [list, dispatch] = useReducer(listReducer, [])

// 往list加内容
const action = {
    type:'add',
    value:'要加的内容'
}
dispatch(action)
// 删除list的内容
const action = {
    type:'del',
    value:要删的索引
}
dispatch(action)

对复用性要求低,可读性好,前端自动化测试方便用 reducer
对复用性高,用useState
使用immer可以不用构建新的对象或者数组。

import {useImmerReducer} from "use-immer"
const [list, dispatch] = useImmerReducer(listReducer, [])
function listReducer(draft, action){
    if(action.type === 'add'){
            直接修改draft即可
            draft.xxx = xxxx 
        }
    }

context 深层组件传值
创建nameContext.js文件


默认值设置在<nameContext.Provider value="szzzz">
孙子组件这么用

传dom,类似vue的插槽。


组件中,setXXX更新数据的时候整个组件会重新执行,为了防止有的是变量会受影响 「重新定义」 就用:
import { useRef} from 'react' const timer = useRef(null) 使用变量时:timer.current
也可获取dom
在父组件中不能直接ref 获得子组件的dom,不推荐, 如果必须要用的话:
子组件这么写:外面包一层forwardRef

import { forwardRef } from 'react'
const 组件名 = forwardRef((props,ref)=>{
    return (<标签 ref={ref}>)
})

如下图所示,如果把请求外部数据的代码这样写在组件里,useState的数据改变时就会重新运行APP 就会重新发送

为了解决:Import { useEffect } from 'react' 渲染完dom后会执行

useEffect(()=>{
    axios
},[]) 空数组的话,就是第一次渲染时执行;如果里面放变量,每次变量【useState】改变它会执行函数;

清除Effect引入的临时内容,防止内存泄露;
return一个函数,里面清理定时器。

操作dom的代码放这里面,因为它在渲染之后运行。
严格模式在线上没有执行两次的问题,意思是在开发的时候尽量让函数是纯函数。
useEffect里面可以返回函数,来清理多余的一个。全局事件绑定也要清理。
在组件中,有一个useState的值改变了整个函数会重新执行,导致里面有一些循环啥的会也跟着执行。【明明是不相关的】
解决:

import { useMemo } from 'react'
const xxx = useMemo(()=>{
    return 处理后的值
},[依赖的变量,他改变时才会走里面的方法])

他和useEffect的区别是useEffect是在render之后执行,而useMemo是按代码编写从上到下顺序执行。

第一个参数,是订阅函数,当发生什么变化的时候才去从第二个参数表述的地方取值。
组件的挂载和销毁有一次,但effect可能会有多次。因为useEffect依赖的变量变化了,就会先销毁在创建
Effect和Event的区别:Effect是依赖数据驱动执行的,Event是由用户操作行为驱动执行的。
正常他会提示要依赖两个变量,这样操作之后就可以只依赖url了。param变化不会让effect运行。

自定义Hook,用来复用逻辑。
要用use开头。 自定义hook内的状态互相独立不会被复用。

useCallback 避免render过程反复重新生成函数
每次组件重新渲染的时候都会重新定义它里面的函数,这样性能差

只有依赖项变化了才会重新执行函数。
useDebugValue 只能写在自定义hook中,类似于console.log 在react的浏览器调试插件里能够看到打印的信息
useImperativeHandle 限制父组件调用子组件DOM的方法或者属性 【当父组件使用子组件ref的时候】
将从父组件传进来的ref和自己的ref做个联系【以前都是直接在子组件使用传进来的ref】
这样就可以只让父组件使用子组件的blur方法 而不是所有的

Profiler 用来打印一些性能相关的时间,比如渲染时间啥的

组件懒加载的写法

Suspense 用来做组件懒加载的体验优化

useDeferredValue 组件切换时会显示loading 然后加载完后会显示要切换的组件,它的作用是可以不显示loading,等加载完后直接显示新组件,加载过程中一直显示老组件。
组件延迟一秒加载


未完待续

前端

请先 登录 再评论