当前位置: 代码网 > it编程>编程语言>Javascript > React 组件中 State 的定义、使用及正确使用方式

React 组件中 State 的定义、使用及正确使用方式

2024年11月25日 Javascript 我要评论
前言在 react 应用开发中,state是组件内部用来存储和管理数据的关键概念。它允许组件根据不同的状态展示不同的 ui。本文将详细介绍state的定义、使用方式以及如何正确地更新state,帮助开

前言

在 react 应用开发中,state 是组件内部用来存储和管理数据的关键概念。它允许组件根据不同的状态展示不同的 ui。本文将详细介绍 state 的定义、使用方式以及如何正确地更新 state,帮助开发者更好地理解和运用这一核心特性。

1.1 state及其特点

state 与 props 类似,但是 state 是私有的,并且完全受控于当前组件

不要直接修改state:构造函数是唯一可以给 this.state 赋值的地方。

state更新可能是异步的:出于性能考虑,react 可能会把多个 setstate() 调用合并成一个调用。

state更新会被合并:当你调用 setstate() 的时候,react 会把你提供的对象合并到当前的 state

1.2 state的定义和使用

目前react中的状态有两种使用方式:

1.2.1 es6的类 - 构造函数

src/index.js

import react from 'react'
import reactdom  from 'react-dom/client'
​
// 引入时,后缀名可以省略,可以在webpack中配置
// import app from './01-app-parent-child'
// import app from './02-app-parent-child-value'
// import app from './03-app-parent-child-value-default'
// import app from './04-app-parent-child-value-default-type'
// import app from './05-app-props-children'
// import app from './06-app-mutiple-props-children'
// import app from './07-app-mouse-tracker'
// import app from './08-app-render-props'
import app from './09-app-state-es6'
​
const root = reactdom.createroot(document.getelementbyid('root'))
​
root.render(<app />)

src/09-app-state-es6.jsx

import react, { component } from 'react';
​
/**
 * es6 规定,子类必须在constructor()方法中调用super(),否则就会报错。
这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,
得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。
如果不调用super()方法,子类就得不到自己的this对象。
​
 es5 的继承机制,是先创造一个独立的子类的实例对象,
 然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。
 es6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,
 然后再将该对象作为子类的实例,即“继承在前,实例在后”
 */
class app extends component {
  // es6的类 - 构造函数
  constructor (props) {
    super(props) // 调用父类的constructor(props)
    this.state = { // 添加子类自己的实例属性和方法,在react中 state作为初始化状态的属性
      date: new date()
    }
  }
  render() {
    return (
      <div>
        现在的时间是:{ this.state.date.tolocaledatestring()  + this.state.date.tolocaletimestring() }
      </div>
    );
  }
}
​
export default app;

1.2.2 es7的类 - 属性初始化器

src/index.js

import react from 'react'
import reactdom  from 'react-dom/client'
​
// 引入时,后缀名可以省略,可以在webpack中配置
// import app from './01-app-parent-child'
// import app from './02-app-parent-child-value'
// import app from './03-app-parent-child-value-default'
// import app from './04-app-parent-child-value-default-type'
// import app from './05-app-props-children'
// import app from './06-app-mutiple-props-children'
// import app from './07-app-mouse-tracker'
// import app from './08-app-render-props'
// import app from './09-app-state-es6'
import app from './10-app-state-es7'
​
const root = reactdom.createroot(document.getelementbyid('root'))
​
root.render(<app />)

src/10-app-state-es7.jsx

import react, { component } from 'react';
​
// 推荐写法
class app extends component {
  state = { // es7 类的属性
    date: new date()
  }
  render() {
    return (
      <div>
        现在的时间是:{ this.state.date.tolocaledatestring()  + this.state.date.tolocaletimestring() }!!!
      </div>
    );
  }
}
​
export default app;

1.3 如何正确的修改state

setstate() 将对组件 state 的更改排入队列,并通知 react 需要使用更新后的 state 重新渲染此组件及其子组件。这是用于更新用户界面以响应事件处理器和处理服务器数据的主要方式.

setstate() 视为请求而不是立即更新组件的命令。为了更好的感知性能,react 会延迟调用它,然后通过一次传递更新多个组件。

setstate() 并不总是立即更新组件。它会批量推迟更新。这使得在调用 setstate() 后立即读取 this.state 成为了隐患。为了消除隐患,请使用 componentdidupdate 或者 setstate 的回调函数(setstate(updater, callback)),这两种方式都可以保证在应用更新后触发。

记住修改状态的三大原则:

不要直接修改 state

state = { a: 10 }
this.state.a = 100 // ❌

state 的更新可能是异步的

state = { a: 10 }
this.setstate({a: this.state.a + 1 })
this.setstate({a: this.state.a + 1 })
this.setstate({a: this.state.a + 1 })
console.log(this.state.a) // 10

state 的更新会被合并

1.4 this.setstate()方法及其特点

setstate() 会对一个组件的 state 对象安排一次更新。当 state 改变了,该组件就会重新渲染。

setstate()可以添加两个参数,

setstate() 的第二个参数为可选的回调函数,它将在 setstate 完成合并并重新渲染组件后执行

1.4.1 传递函数

参数一为带有形式参数的 updater 函数:

this.setstate((state, props) => statechange[, callback] )

src/index.js

import react from 'react'
import reactdom  from 'react-dom/client'
​
// 引入时,后缀名可以省略,可以在webpack中配置
// import app from './01-app-parent-child'
// import app from './02-app-parent-child-value'
// import app from './03-app-parent-child-value-default'
// import app from './04-app-parent-child-value-default-type'
// import app from './05-app-props-children'
// import app from './06-app-mutiple-props-children'
// import app from './07-app-mouse-tracker'
// import app from './08-app-render-props'
// import app from './09-app-state-es6'
// import app from './10-app-state-es7'
import app from './11-app-setstate-function'
​
const root = reactdom.createroot(document.getelementbyid('root'))
​
root.render(<app />)

src/11-app-setstate-function.jsx

import react, { component } from 'react';
​
class app extends component {
  state = {
    count: 100
  }
  render() {
    return (
      <div>
        { this.state.count }
        <button onclick={ () => {
          this.setstate((state, props) => {
            console.log(state, props)
            return {
              count: state.count + 1
            }
          })
          this.setstate((state, props) => {
            console.log(state, props)
            return {
              count: state.count + 1
            }
          })
          this.setstate((state, props) => {
            console.log(state, props)
            return {
              count: state.count + 1
            }
          })
        } }>加</button>
      </div>
    );
  }
}
​
export default app

updater 函数中接收的 stateprops 都保证为最新。updater 的返回值会与 state 进行浅合并。

1.4.2 传递对象

src/index.js

import react from 'react'
import reactdom  from 'react-dom/client'
​
// 引入时,后缀名可以省略,可以在webpack中配置
// import app from './01-app-parent-child'
// import app from './02-app-parent-child-value'
// import app from './03-app-parent-child-value-default'
// import app from './04-app-parent-child-value-default-type'
// import app from './05-app-props-children'
// import app from './06-app-mutiple-props-children'
// import app from './07-app-mouse-tracker'
// import app from './08-app-render-props'
// import app from './09-app-state-es6'
// import app from './10-app-state-es7'
// import app from './11-app-setstate-function'
import app from './12-app-setstate-object'
​
const root = reactdom.createroot(document.getelementbyid('root'))
​
root.render(<app />)

src/12-app-setstate-object.jsx

import react, { component } from 'react';
// 为什么?
// const obj = { a: 100 }
// es6 中对象合并
// const newobj = object.assign(obj, {a: 100 + 1}, {a: 100 + 1}, {a: 100 + 1})
// console.log(newobj) // { a: 101 }
​
class app extends component {
  state = {
    count: 10
  }
  render() {
    return (
      <div>
        { this.state.count }
        <button onclick={ () => {
          this.setstate({
            count: this.state.count + 1
          })
          this.setstate({
            count: this.state.count + 1
          })
          this.setstate({
            count: this.state.count + 1
          })
          console.log(this.state.count)
        } }>加</button>
      </div>
    );
  }
}
​
export default app;

这种形式的 setstate() 是异步的,并且在同一周期内会对多个 setstate 进行批处理,相当于

object.assign(
prevstate,
{count: this.state.count + 1},
{count: this.state.count + 1},
...
)

后调用的 setstate() 将覆盖同一周期内先调用 setstate 的值,因此商品数仅增加一次。如果后续状态取决于当前状态,建议使用 updater 函数的形式代替(前面案例已经实现)。或者在第二个参数中再继续操作。

src/index.js

import react from 'react'
import reactdom  from 'react-dom/client'
​
// 引入时,后缀名可以省略,可以在webpack中配置
// import app from './01-app-parent-child'
// import app from './02-app-parent-child-value'
// import app from './03-app-parent-child-value-default'
// import app from './04-app-parent-child-value-default-type'
// import app from './05-app-props-children'
// import app from './06-app-mutiple-props-children'
// import app from './07-app-mouse-tracker'
// import app from './08-app-render-props'
// import app from './09-app-state-es6'
// import app from './10-app-state-es7'
// import app from './11-app-setstate-function'
// import app from './12-app-setstate-object'
import app from './13-app-setstate-callback'
​
const root = reactdom.createroot(document.getelementbyid('root'))
​
root.render(<app />)

src/13-app-setstate-callback.jsx

import react, { component } from 'react';
​
​
class app extends component {
  state = {
    count: 10
  }
  render() {
    return (
      <div>
        { this.state.count }
        <button onclick={ () => {
          this.setstate({
            count: this.state.count + 1
          }, () => {
            this.setstate({
              count: this.state.count + 1
            }, () => {
              this.setstate({
                count: this.state.count + 1
              })
            })
          })
          console.log(this.state.count) // 10
        } }>加</button>
      </div>
    );
  }
}
​
export default app;

思考题:

1.何时以及为什么 setstate() 会批量执行?

2.为什么不直接更新 this.state?

总结

通过本文的介绍,我们了解了 state 在 react 组件中的重要性,以及如何在 es6 和 es7 类组件中定义和使用 state。同时,我们还探讨了正确更新 state 的方法,包括使用 setstate() 方法时需要注意的事项。遵循这些最佳实践,可以帮助我们避免常见的陷阱,提高应用的性能和可靠性。

到此这篇关于react 组件中 state 的定义、使用及正确更新方式的文章就介绍到这了,更多相关react state 组件内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

  • 如何在ubuntu18.04安装node 14.16.0

    这里演示安装node 14.16.0,其他版本也一样的安装步骤,需要注意11.检查本机服务器类型注:有的是x64,有的是arm,先查清楚是什么类型再进行下载,否则会存在编译出错的问…

    2024年11月25日 编程语言
  • Node.js使用Playwright自动化测试页面性能

    Node.js使用Playwright自动化测试页面性能

    概要对于现在的网站而言,性能的重要性不言而喻,每一家公司的网站都在追求更快地性能,更好地体验,但是,该怎么去找到影响网站速度的因素,如何优化性能,这是一个非常考... [阅读全文]
  • vue实现直连mysql的方法步骤

    最近又搞了个小项目,单机版本的内部考勤管理系统,直接部署在对方的工作电脑上,不需要在云端部署,因为项目本身就小,我就没配置后端同事进行开发,而是通过vue直连mysql进行业务开发…

    2024年11月25日 编程语言
  • Node.js中Playwright库使用指南

    Node.js中Playwright库使用指南

    概要playwright 是一个用于做自动化测试的开源框架,它允许你通过代码去自动化操作浏览器,它还可以跨浏览器测试,包括chrome,edge、firefox... [阅读全文]
  • Vue 3 中 toRaw 的用法详细讲解

    Vue 3 中 toRaw 的用法详细讲解

    toraw 是 vue 3 提供的一个 api,主要用于从 vue 的响应式对象中获取其对应的原始非响应式对象。1.toraw 的作用1、获取原始对象当对象被 ... [阅读全文]
  • 前端错误日志上报的超详细解决方案

    前言项目上线之后,用户如果出现错误(代码报错、资源加载失败以及其他情况),基本上没有办法复现,如果用户出了问题但是不反馈或直接不用了,对开发者或公司来说都是损失。由于我这个项目比较…

    2024年11月25日 编程语言

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com