React笔记

react官网 :React 官方中文文档

1.jsx


1.Jsx概念:jsx是一个 JavaScript 的语法扩展,它具有 JavaScript 的全部功能。
2. jsx是一种语法糖是js的一种语法扩展,它跟模版语言很接近,但它具备js的能力。
3.jsx的优点
开发效率: 使用jsx编写模版简单快速 执行效率:jsx编译为js代码后进行优化,执行更快 类型安全:在编译过程中就会发现错误
4.jsx的原理
用babel-loader会将JSX编译成React.creatElement()

1.React脚手架npx create-raect-app 项目名称 

2.在React中组件名称首字母必须要大写

1.jsx两种写法

  1. jsx元素创建和使用

JSX 全称 JavaScript XML,是React 定义的一种类似于 XML 的 JS 扩展语法:JS + XML,本质是 React.createElement(component, props, ...children) 方法的语法糖

示例


//jsx元素的创建与使用

//声明一个name变量
const name = 'Josh Perez';

//创建一个jsx元素
//这里不需要使用引号包裹  如果元素结构过于复杂使用()包裹
const element = <h1>Hello, {name}</h1> 

//*组件首字母必须大写

function DemoA() {
  return element ;
}
export default DemoA
/*
标签首字母
    (1).若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错。
    (2).若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
*/

2.React.createElement的形式
Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。
  • Jsx

语法:

  • React.createElement(a, {'b'}, ['c'])

  • 第一个参数 a:表示元素的类型,比如:h1, div 等。

  • 第二个参数 b:表示该元素上的属性,使用 JavaScript 对象方式表示。

  • 第三个参数 c:表示该元素内部的内容,可以是文字,可以继续嵌套另外一个

示例


function DemoA() {
  //使用React.createElement创建一个jsx
  return React.createElement('div',//第一位参数元素类型
    { 'className': 'box', 'title': 'haha' },//元素属性
    [
      React.createElement("span",{key:1},"我是span"),//第一为参数 的子元素 
      React.createElement("a",{'href':"https://www.baidu.com/",key:2},"百度")
    ])
}

  • React.creaetElement

  • 这种方法是用 React 的 createElement 来创建 React DOM。

2.在jsx中嵌套表达式

  • 在jsx中使用变量,需要把他放在{}内

  • 在jsx元素中,你要嵌套表达式,必须使用{}包起来

  • 在jsx元素中,看到{}你要知道里面放的都是表达式。任何有值的内容都是表达式。

  • 在jsx元素定义的视图比较复杂的时候 标签需要换行对齐 建议使用()包裹

3.JSX 特定属性(行内样式)

你可以通过使用引号,来将属性值指定为字符串字面量


const element = <div tabIndex="0"></div>;

也可以使用大括号,来在属性值中插入一个 JavaScript 表达式

语法:


//内联样式,要用style={{key:value}}的形式去写。
const element = <img src={user.avatarUrl}></img>;

在属性中嵌入 JavaScript 表达式时,不要在大括号外面加上引号。你应该仅使用引号(对于字符串值)或大括号(对于表达式)中的一个,对于同一属性不能同时使用这两种符号。

警告:
因为 JSX 语法上更接近 JavaScript 而不是 HTML,所以 React DOM 使用 camelCase(小驼峰命名)来定义属性的名称,而不使用 HTML 属性名称的命名约定。
例如,JSX 里的 class 变成了 className,而 tabindex 则变为 tabIndex

4.jsx元素不可变性

  • jsx元素本质是一个对象,这个对象是不可变对象

  • 如果确实需要更改元素的属性,需要重新创建JSX元素,从新reader 节点

  • react 的dom 操作的是react 自己创建出来的虚拟dom, 不会导致浏览器的重绘和重排

5.jsx做函数的入参

  • JSX 表达式会被转为普通 JavaScript 函数调用,并且对其取值后得到 JavaScript 对象。

6.jsx元素中有三个变化的属性

  • class 变成了 className

  • for 变成了 htmlFor

  • tabindex 变成了tabIndex

7.jsx元素中新增了三个属性

  • key 用于列表渲染

  • ref 方便DOM操作

  • dangerouslySetInnerHTML 用来渲染一片html字符串

8.jsx只能有一个根标签


import React from "react";
let a=100
function foo(user) {
  return `${user.firstName} ${user.lastName}`
}
function DemoA() {
  return (
    <div>
      <h3>{ a+110}</h3>
      <h3>{ `${a}100`}</h3>
      <h3>{ foo({firstName:'wc',lastName:'www'})}</h3>
    </div>
  )
}
export default DemoA

9.使用 JSX 指定子元素

假如一个标签里面没有内容,你可以使用 /> 来闭合标签,就像 XML 语法一样:


const element = <img src={user.avatarUrl} />;

JSX 标签里能够包含很多子元素:


const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

10.在使用JSX时,如果是数组,可以直接渲染

示例


function DemoA() {
  return (
    <div>
      <div><h1>{ ['a','b','c']}</h1></div>
    </div>
  )
}
export default DemoA

2.组件 && Props


组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。

1.在react,组件两种写法 分为 类组件 和函数组件(主流)

  • 类组件组件 性能差

  • 类组件必须要写一个声明周期函数 render

  • 在reader中需要使用return返回试图模板

  • 类组件的特点 使用的是ES6中面向对象编程的模式

  • 里面有生命周期

  • 有this

  • 有state 有上下文

  • 有ref


//类体验组件的书写
import { Component } from "react";
//*类组件
//*特点 使用ES6面向对象的语法 里面有生命周期 有this 有state 也有上下文 有ref
//*缺点 相比函数方式组件 性能差 现在类组件不是主流
class DemoA extends Component{
  //*render是生命周期
  render() {
    return(<h1>类组件</h1>)
  }
}

  • 函数式组件 性能高 没有生命周 this 上下文 ref 使用函数式编程 配合hook实现类组件的特点

  • 特点使用函数式编程

  • 没有生命周期 this 上下文 ref

  • 函数式组件配合hook使用 可以达到组件的功能


//*函数式组件,从React诞生既有这种写法
//*特点用的式函数式编程 没有生命周期等 函数式组件配合hook 可以达到类组件的功能
//*优点 相比组件性能更好
//* 在React 组件名字必须大写
function DemoB() {
  return(<h1>函数式组件</h1>)
}
export default DemoB

2.Props

1.Props 的只读性

2.{...props}
  • 可以传递多种类型

3.props.children
在使用组件时,如果组件使用双标签,在双标签之间就可以写内容,在双标签之间写的内容是通过props.children来接收的,props.children可以是任意类型的数据,基本数据类型可以,引用数据类型也可以,也可以是函数。
  • 可以传递一个jsx,也可以传递一个函数,函数返回一个jsx

3.State & 生命周期


1.State

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
1.state和setState
  1. 在函数内不使用setState修改状态render不会执行 做不到模板刷新

  1. 修改状态的值的时候避免直接修改,新状态是由老状态计算出来的

2.this.setState有两种写法:
  • this.setState({}, callback) 在修改状态时,当新值与旧值无关时,推荐使用这种写法,callback表示当状态修改后,自动执行,当状态修完后,有一些业务逻辑放到callback中。

  • this.setState((state, props)=>({}), callback) 新值与旧值有关时,新值由旧值计算而来,形参state永远表示旧值,建议使用这种写法。callback表示当状态修改后,自动执行,当状态修完后,有一些业务逻辑放到callback中。

3.setState 修改状态的同步和异步问题
  • react17 及之前版本,如果你把当前的操作不写在合成事件中,则 setState 它就是同步的,在React18中,this.setState任务时候都是异步的

  • setState 在执行的过程中,它会判断当的执行环境,如果为宏任务等,则它会立即执行。

  • 在宏任务,Promise.then中是同步的。所谓的React合成事件是指on*系列事件,生命周期函数

5.事件绑定
  • 利用ES5中的bind中手动绑定this

  • 利用ES6中的箭头函数自动绑定this

6.状态在函数组件中的使用
  • 函数组件中是不能定义状态,但是配合hook可以定义状态,hook类似于vue3中的组合式API。

总结

  1. 成员属性 state 它是一个特殊的属性,它是当前类的私有数据,只有在当前的组件中才能操作里面的数据

  1. 状态( state )即数据,是组件内部的私有数据,只能在组件内部使用,和vue中data差不多,不过它没有像vue中的data进行了数据劫持

  1. 不要直接修改 State此代码不会重新渲染组件

  1. state的值是对象,表示一个组件中可以有多个数据

  1. 修改状态的值的时候避免直接修改,新状态是由老状态计算出来的

  1. 通过this.state来获取状态,react 中没有做数据代理

  1. state 它是类的一个成员属性

  1. state 中的数据可读可写的

  1. state 的更新可能是异步的

2.类组件的生命周期

vue组件的生命周期,有些并不重要,基本上用不到,但是React的生命周期都非常重要,没有多余的,关于生命周期有非常多的面试题。
只有类组件才会有生命周期钩子函数,函数式组件没有生命周期钩子的函数的。

生命周期函数很多,我们需要掌握6个:

  • 装载阶段(3个):constructor, render, componentDidMount

  • 更新阶段(2个):render,componentDidUpdate

  • 卸载阶段(1个):componentWillUnmount

1.constructor数据的初始化。
接收props和context,当想在函数内使用这两个参数需要在super传入参数,当使用constructor时必须使用super,否则可能会有this的指向问题,如果不初始化state或者不进行方法绑定,则可以不为组件实现构造函数;
1.constructor中,this的绑定
  • 利用ES5中的bind中手动绑定this

  • 利用ES6中的箭头函数自动绑定this

  • 就是在constructor中进行this绑定

2.constructor中的props
在constructor中有一个props,这个props是用来接收父传递的数据的,props的数据流和state的数据流必须独立。

3.在constructor中,不能调用setState方法

constructor中,不能调用接口,不能进行DOM操作,不能开定时器... 一切和业务相关的代码都不能写在constructor钩子函数中。

总结在constructor中,可以做什么:

  • 定义状态

  • 绑定方法的this

2.render(装载)
作用:用于返回组件的视图结构,这个结构在vue叫模板,在react中叫jsx。它的背后是生成一棵Fiber树,在vue中叫虚拟DOM,在React叫Fiber树,早期的React也是使用的虚拟DOM。

1.在render函数中,不能调用setState(会死循环,每一次setState,都会重新render)

2.render函数会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点,并重新渲染。

3.当render被调用时,他会检查this.props.和this.state的变化并返回以下类型之一:

1.通过jsx创建的react元素 2.数组或者fragments:使得render可以返回多个元素 3.Portals:可以渲染子节点到不同的dom树上 4.字符串或数值类型:他们在dom中会被渲染为文本节点 5.布尔类型或者null:什么都不渲染

render是一个函数,这个函数返回一个jsx,jsx叫jsx元素,本质是一个对象,创建jsx元素有2种方法,一种是直接使用jsx,另外一种是React.creeateEleement。也就说,调用render函数,会生成棵Fiber树,类似于Vue中的虚拟DOM,这个Fiber树是双向链表结构。生成这课Fiber树的过程是异步的,生成的过程是可以中断,能不能中断是看浏览器忙不忙,如果浏览器比较忙,就可能中断,等待浏览器不忙时,会继续生成,直到Fiber树创建完成。然后会进行协调运算,这个协调运算类似于Vue中的Diff运算,也就是一棵老的Fiber树和一棵新的Fiber树进行对比运算。运算对比后,就会进入到commmit提交阶段,一次性提交Fiber更新DOM。
3.componentDidMount(装载)
在组件挂在后(插入到dom树中)后立即调用
可以在这里调用Ajax请求,返回的数据可以通过setState使组件重新渲染,或者添加订阅,但是要在conponentWillUnmount中取消订阅

类似于vue中的mounted,表示页面第一次渲染完成。在这个钩子函数中可以做什么?

  • 调用接口

  • 开定时器

  • DOM操作

  • 编写业务逻辑

4.componentDidUpdate(更新)
相当于Vue中的updated,表示页面再次渲染成功。
监听器是用来监听数据是否变化,updated表示数据变化了,会执行updated,也就是说数据变化了,在updated也可以监听到了。要监听数据变化,在vue中,使用监听器比使用updated更方便。在react中是没有监听器的概念的,在React中实现类似于Vue的监听器的功能,需要使用compoentDidUpdate钩子函数了。

1.不使用componentDidUpdate,实现类似于Vue中的监听器方法

this.setState({}/fn, callback) 利用callback也可以感知到数据变化了。推荐使用componentDidUpdate。因为多个setState会合并,合并后,callback也会出问题。

2.该方法调用setState,一定需要一个出口(条件语句,定时器),否则一直更新会造成死循环

总结:

  • componentDidUpdate中可以调用setState,但是必须给出出口(终止条件),否则会产生死循环,循环到一定次数就会报错。

  • componentDidUpdate可以模拟vue中的监听器,特别需要注意终止条件。

  • 除了使用componentDidUpdate实现监听器之外,还可以使用this.setState中的callback来实现,不建议使用,因为setState会合并,callback容易出问题。

6.componentWillUnmount(卸载)
在组件卸载和销毁之前调用
在这执行必要的清理操作,例如,清除timer(setTimeout,setInterval),取消网络请求,或者取消在 componentDidMount的订阅,移除所有监听

类似于Vue中的beforeDestroy,表示组件即将销毁。在这里我们可以:

  • 清缓存

  • 清除定时器

  • 关闭长连接

  • 销毁DOM元素

  • ....

componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

7.shouldComponentUpdate
它是控制更新阶段的开关,说白了,就是来控制是否更新,当返回true就正常更新,当返回false时就不更新。

默认情况下,没有写的话,就是返回true,看一下state参数,如下:

shouldComponentUpdate,返回true时,正常更新,返回false时,不执行更新阶段。注意细:

  • 当执行forceUpdate时,会绕过shouldComponentUpdate方法,一定会进入到更新阶段。

  • shouldComponentUpdate,可以使用PureCompoentf替代

为什么要使用这个开关呢?

答:组件中有很多状态,有些状态会参与到界面刷新,也就是说有些状态变了,需要更新页面。但是还有一些状态是不参与到界面更新,也就是状态变了,不需要更新页面的,此时就体现出开关的重要性了。参与页面更新的状态,状态变化了,在showCompoentUpdate中返回true正常更新。如果没有参与页面刷新的状态变化了,在shouldCompoentUpdate中返回false,就需要再次调用render。这样,就会少生成一次Fiber树。这个钩子函数是用来性能调优的,可以阻塞掉那些不参与视图渲染的状态更新导致的Fiber生成。

React组件渲染(更新)流程,由两个阶段组成的,一个叫render阶段,一个叫commit阶段,如下:

render阶段:

  • 目标是生成Fiber树,这个过程是异步的,是可中断,并且不会执行任何副作用。到底中断与否,看的是浏览器主线程的忙不忙。

commit阶段:

  • 目的是把协调运算的结果,一次性提交渲染或更新真实DOM。这个过程在V18之前是不可中断的,在V18中是可以人为中

4.状态提升


实现方式是 利用最近的 共同的父级组件中, 用props的方式传过去到两个子组件,props中传的是一个setState的方法,通过子组件触发props传过去的方法,进而调用父级组件的setState的方法,改变了父级组件的state,调用父级组件的add方法,进而同时改变了两个子级组件的数据。

1.什么是状态提升

一个父组件,下面有两个子组件,这两个子组件,需要通信,通常会把这个状态定义到父组件中,通过父传子,再通过子传父,实现兄弟之间的通信,状态提供到父上面,就是所谓的状态提升。

落地到代码上就是所谓的父传子,和子传父。在vue中:

  • 父传子:自定义属性 + props

  • 子传父:自定义事件 + emit()

在react中没有所谓的自定义属性或自定义事件,都是所谓props。也就是说研究状态提升就是研究所谓的父子通信。

  1. 摄氏度案例


//摄氏度官方案例 状态提示
import { Component,useState } from "react";
​
class Fahrenheit extends Component{
  render() {
    const { value,onChange } = this.props
    const change = (e) => {
      let temper = (Number(e.target.value) - 32) * 5 / 9
      onChange(Number(temper))
    }
    return(
      <div>
        <label>华氏温度:</label>
        <input type="text" value={value*9/5+32} onChange={change} />
      </div>
    )
  }
}
function Celsius(props) {
  let { value,onChange } = props
  const change = (e) => {
    onChange(e.target.value)
  }
  return (
    <div>
      <label >摄氏温度:</label>
      <input type="text" value={value} onChange={ change} />
    </div>
  )
}
​
function DemoA() {
  //设置一个双向绑定数值
  const [temper, setTemper] = useState(0)
  let change = (val) => {
    setTemper(val)
  }
  return (
    <div>
      <Fahrenheit value={temper} onChange={change}></Fahrenheit>
      <hr />
      <Celsius value={temper} onChange={change}></Celsius>
    </div>
  )
}
export default DemoA

总结:

  • 在React中,一般不讨论自定义属性或自定义事件,写在组件上的都叫props。props的值可以是基本数据,也可以是对象,也可以是数组,当然也可以是函数,也可以是jsx。

  • 如果是函数,函数分两类,一类叫事件函数,另一类叫渲染函数。如果是事件函数,建议以on打头,如果是渲染函数,建议不要使用on打头。


  <Modela="hello"b={110} onChange={()=>{}} footer={()=>(<footer/>)}></Model>
  onChange={()=>{}} 叫事件函数
  footer={()=>(<footer/>)}  叫渲染函数
  • 所谓的状态提升,就是把一个状态提升到父组件中,实现父传子,实现子传父。

5.hooks


React Hooks就是加强版的函数组件,可以完全不使用 class,就能写出一个全功能的组件
作用:用于在函数式组件中模拟出类组件的功能。如:state,生命周期,ref,上下文...

1.Hook函数(9种)

  1. State Hook

useState:状态钩子 使用在函数式组件中定义状态 相当于类组件的State和setState,进行状态数据的读写操作

语法、参数及返回值说明::


const[xxx, setXxx]= React.useState(initValue)//initValue  初始化值
  • 参数: 第一次初始化指定的值在内部作缓存

  • 返回值: 包含2个元素的数组,第1个为内部当前状态值,第2个为更新状态值的函数

setXxx()2种写法:

  • setXxx(newValue): 参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值

  • setXxx(value => newValue): 参数为函数,接收原本的状态值,返回新的状态值,内部用其覆盖原来的状态值

  • 使用const 定义 避免直接修改状态 代码不会重新渲染组件 使用setXxx修改状态 会重新渲染组件

2.Effect Hook

useEffect():副作用钩子用来模拟类组件中的生命周期的,不是模拟所有的生命周期,是模拟这三个componentDidMount/componentDidUpdate/componentWillUnmount生命周期。

语法、参数及返回值说明:


useEffect(() => { 
      // 在此可以执行任何带副作用操作  compoentDidMount 挂载完成
      return () => { // 在组件卸载前执行
        // 在此做一些收尾工作, 比如清除定时器/取消订阅等  清除副作用类似于 消除componentWillUnmount。
      }
}, [stateValue]) // 依赖数组 当数组的值发生变化 useEffect()就会执行。  监听componentDidUpdate

参数、返回值说明:

  • 当没有依赖时候,初始化的时候执行副作用操作,重新render 会先清除副作用 在执行副作用操作

  • 当有“依赖数组”并且没参数,初始化的时候执行副作用操作,重新render,什么都不执行

  • 当有“依赖数组”这个参数时,但是不是一个空数组,初始化的时候执行副作用操作,有且仅有当“依赖数组"中的变量发生变化导致重新render时会先清除副作用 在执行副作用操作

1.vue中的watchEffect和useEffect 的区别

vue中的watchEffect会自动依赖依赖,React中的useEffect,需要手动指定依赖。

2.注意细节:
  • useEffect是用来执行副作用,建议一个useEffect只执行一个副作用。不要在同一个useEffect中同时执行多个副作用。

  • 在函数式组件中,不要把副作用直接暴露在函数体内,一定要使用useEffect进行控制。

3.React中的副作用操作:
  • 发ajax请求数据获取

  • 设置订阅 / 启动定时器

  • 手动更改真实DOM

3.LayoutEffect Hook

useLayoutEffect() :和useEffect相同,都是用来执行副作用。

区别在于useLayoutEffect执行时候更早,

useLayoutEffect和useEffect最大的区别就是一个是同步,一个是异步。

在这个hook中,不能进行ref或dom操作。

4.Context Hook

useContext():共享状态钩子,作用就是可以做状态的分发,在React16.X以后支持,避免了react逐层通过Props传递数据。

使用语法和说明:

  1. 创建Context容器对象:


//第一种
const XxxContext = React.createContext()
//第二种
const ThemeContext=React.createContext()
const { Provider, Consumer } = ThemeContext

渲染子组件时,外面包裹xxxContext.Provider, 通过value属性给后代组件传递数据:


第一种
<xxxContext.Provider value={数据}>	
      <子组件/>
</xxxContext.Provider>

//第二种
 <Provider value={数据}>
     <子组件/>
</Provider>

后代组件读取数据:


const {} = useContext(XxxContext)
//第二种
 <Consumer >
        {
          (ctx) => {//ctx数据
            return (
              <div style={ctx}>
                <h3>我是孩子组件</h3>
              </div>
            )
            }
        }
   </Consumer >
前景色案例

import React,{PureComponent,useState} from "react";
const ThemeContext=React.createContext()
const { Provider, Consumer } = ThemeContext

class Child extends PureComponent{
  render() {
    return (
      <Consumer >
        {
          (ctx) => {
            return (
              <div style={ctx}>
                <h3>我是孩子组件</h3>
              </div>
            )
            }
        }
      </Consumer >
    )
    
    
  }
}
function Parent() {
  return (
    <div>
      <h2>父组件</h2>
      <Child></Child>
    </div>
  )
}
function ThemeToggle({ theme, onChange }) {
  
  const change = (e) => {
    let key = e.target.name;
    let val = e.target.value;
    onChange({...theme,[key]:val})
  }
  return (
    <div>
        前景色:<input type="color" name="color" value={theme.color} onChange={change }></input>
        背景色:<input type="color" name='background' value={theme.background} onChange={change }></input>
    </div>
  )
}
function DemoA() {
const [theme, setTheme] = useState({ color: "#000000", background: "#ffffff" })
  return (
    <Provider value={theme}>
      <div>
        <div>
          <h2>页面</h2>
          <hr />
          <Parent></Parent>
        </div>
        <ThemeToggle theme={theme} onChange={(e)=>setTheme(e)}></ThemeToggle>
      </div>
    </Provider>
  )
}
export default DemoA
5.Ref Hook

userRefef():Ref Hook可以在函数组件中存储、查找组件内的标签或任意其它数据

语法和参数说明:


const refContainer =useRef()

useRef返回一个可变的ref对象,useRef接受一个参数绑定在返回的ref对象的current属性上,返回的ref对象在整个生命周期中保持不变。

作用:保存标签对象,功能与React.createRef()一样

例子:input上绑定一个ref,使得input在渲染后自动焦点聚焦


import{ useRef,useEffect} from "react";
const RefComponent = () => {
    let inputRef = useRef(null);
    useEffect(() => {
        inputRef.current.focus();
    })
    return (
        <input type="text" ref={inputRef}/>
    ) 
}
6.Memo Hook

useMemo(): 主要用来解决使用React hooks产生的无用渲染的性能问题,类似于vue中的计算属性。

语法和参数说明:


const cacheSomething =useMemo(create,deps)
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • create:第一个参数为一个函数,函数的返回值作为缓存值

  • deps: 第二个参数为一个数组,存放当前 useMemo 的依赖项,在函数组件下一次执行的时候,会对比 deps 依赖项里面的状态,是否有改变,如果有改变重新执行 create ,得到新的缓存值。

  • cacheSomething:返回值,执行 create 的返回值。如果 deps 中有依赖项改变,返回的重新执行 create 产生的值,否则取上一次缓存

7、Callback Hook

useCallback(): 主要是为了性能的优化

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)

可以认为是对依赖项的监听,接受一个回调函数和依赖项数组。

useCallback会返回一个函数的memoized(记忆的)值。

该回调函数仅在某个依赖项改变时才会

在依赖不变的情况下,多次定义的时候,返回的值是相同的

语法:


const fn =useCallback(()=>{},[依赖数组])
8.Reducer Hook

useReducer():Action钩子。在使用React的过程中,如遇到状态管理,一般会用到Redux。而React本身是不提供状态管理的。而useReducer() 提供了状态管理

useState是用来定义状态的,如果有很多的状态,通过需要写多个useState。使用useReducer有一个好处,一个useReducer可以代替多个useState。是在React函数式组件中模块Redux的数据流。

语法:


const[state, dispath / foreUpdate / setState]=useReducer(reducer,{
    初始值
})

案例


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

// state表示状态,action表示信号,根据不同的信号,就可以针对性地修改状态
// reducer 是管理员的意思,要修改状态必须通过reducer
// 管理员根据信号进行状态的修改
// 修改状态的流程:1)对于state进行深copy  2)修改更新state  3)返回修改后的state
const reducer = (state, action) => {
    let newState = JSON.parse(JSON.stringify(state)); // 1)对于state进行深copy
    // 根据信号更新state
    switch (action.type) {  // action是一个对象,对象中有一个type,不同的type表示不同的信号
        case "NUM_ADD":
            newState.num += 1
            break;
        case "NUM_SUB":
            newState.num -= 1
            break;
    }
    return newState;
}
// 定义初始值
const initState = {
    num: 1,
    list: ["a", "b"],
    falg: true
}

const A = props => {
    // dispatch 是用来派发一个action,管理员就可以收到action
    const [state, dispatch] = useReducer(reducer, initState);
    return (
        <div>
            <h2 >函数组件</h2>
            <h3>{state.num}</h3>
            <h3>{state.list}</h3>
            <button onClick={() => dispatch({ type: "NUM_ADD" })}>+1</button>
            <button onClick={() => dispatch({ type: "NUM_SUB" })}>-1</button>
        </div>
    )
}
export default A
9.Id hooks

useId(),返回一个唯一的标识,在函数式组件的整个运行过程中都是唯一的。

注意:是V18版本新增的。

语法:


import { useId } from "react"
let ids = usrId()
10.DeferredValue hooks

useDeferredValue(),和防抖类似。和真正的防抖区别在于,这个hook所延迟的时间是不确定,由浏览器自己决定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React.createElementReact中用来创建React元素的方法。它接受三个参数: 类型(type),属性(props),和子元素(children)。 在使用JSX语法时,JSX会被编译为React.createElement()的调用,从而创建React元素。 下面是一个示例代码,展示了如何使用React.createElement创建React元素: ```javascript var cli = React.createClass({ render: function() { return ( <li> {this.props.children} </li> ) } }) var child1 = React.createElement(cli, {key:'F'}, 'First Text Content'); var child2 = React.createElement(cli, {key:'S'}, 'Second Text Content'); var child3 = React.createElement(cli, {key:'T'}, 'Third Text Content'); var root = React.createElement('ul', { className: 'my-list' }, [child1, child2, child3]); ReactDOM.render( root, document.getElementById('content') ); ``` 在上述代码中,使用React.createElement创建了三个li元素(child1, child2, child3),然后这些li元素作为数组传入到React.createElement中创建了一个ul元素(root)。最后,使用ReactDOM.render将root渲染到id为'content'的DOM元素中。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [React.createElement方法使用详解](https://blog.csdn.net/lixingshi/article/details/53857397)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [leslie1943#blog#React-JSXReact.createElement1](https://download.csdn.net/download/weixin_35804761/86252862)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值