翼度科技»论坛 编程开发 JavaScript 查看内容

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

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
前言

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

1.1 state及其特点

State 与 props 类似,但是 state 是私有的,并且完全受控于当前组件
不要直接修改state:构造函数是唯一可以给
  1. this.state
复制代码
赋值的地方。
state更新可能是异步的:出于性能考虑,React 可能会把多个
  1. setState()
复制代码
调用合并成一个调用。
state更新会被合并:当你调用
  1. setState()
复制代码
的时候,React 会把你提供的对象合并到当前的 state

1.2 state的定义和使用

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

1.2.1 es6的类 - 构造函数
  1. src/index.js
复制代码
  1. import React from 'react'
  2. import ReactDOM  from 'react-dom/client'

  3. // 引入时,后缀名可以省略,可以在webpack中配置
  4. // import App from './01-App-parent-child'
  5. // import App from './02-App-parent-child-value'
  6. // import App from './03-App-parent-child-value-default'
  7. // import App from './04-App-parent-child-value-default-type'
  8. // import App from './05-App-props-children'
  9. // import App from './06-App-mutiple-props-children'
  10. // import App from './07-App-mouse-tracker'
  11. // import App from './08-App-render-props'
  12. import App from './09-App-state-es6'

  13. const root = ReactDOM.createRoot(document.getElementById('root'))

  14. root.render(<App />)
复制代码
  1. src/09-App-state-es6.jsx
复制代码
  1. import React, { Component } from 'react';

  2. /**
  3. * ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错。
  4. 这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,
  5. 得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。
  6. 如果不调用super()方法,子类就得不到自己的this对象。

  7. ES5 的继承机制,是先创造一个独立的子类的实例对象,
  8. 然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。
  9. ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,
  10. 然后再将该对象作为子类的实例,即“继承在前,实例在后”
  11. */
  12. class App extends Component {
  13.   // es6的类 - 构造函数
  14.   constructor (props) {
  15.     super(props) // 调用父类的constructor(props)
  16.     this.state = { // 添加子类自己的实例属性和方法,在react中 state作为初始化状态的属性
  17.       date: new Date()
  18.     }
  19.   }
  20.   render() {
  21.     return (
  22.       <div>
  23.         现在的时间是:{ this.state.date.toLocaleDateString()  + this.state.date.toLocaleTimeString() }
  24.       </div>
  25.     );
  26.   }
  27. }

  28. export default App;
复制代码
1.2.2 es7的类 - 属性初始化器
  1. src/index.js
复制代码
  1. import React from 'react'
  2. import ReactDOM  from 'react-dom/client'

  3. // 引入时,后缀名可以省略,可以在webpack中配置
  4. // import App from './01-App-parent-child'
  5. // import App from './02-App-parent-child-value'
  6. // import App from './03-App-parent-child-value-default'
  7. // import App from './04-App-parent-child-value-default-type'
  8. // import App from './05-App-props-children'
  9. // import App from './06-App-mutiple-props-children'
  10. // import App from './07-App-mouse-tracker'
  11. // import App from './08-App-render-props'
  12. // import App from './09-App-state-es6'
  13. import App from './10-App-state-es7'

  14. const root = ReactDOM.createRoot(document.getElementById('root'))

  15. root.render(<App />)
复制代码
  1. src/10-App-state-es7.jsx
复制代码
  1. import React, { Component } from 'react';

  2. // 推荐写法
  3. class App extends Component {
  4.   state = { // es7 类的属性
  5.     date: new Date()
  6.   }
  7.   render() {
  8.     return (
  9.       <div>
  10.         现在的时间是:{ this.state.date.toLocaleDateString()  + this.state.date.toLocaleTimeString() }!!!
  11.       </div>
  12.     );
  13.   }
  14. }

  15. export default App;
复制代码
1.3 如何正确的修改state
  1. setState()
复制代码
将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。这是用于更新用户界面以响应事件处理器和处理服务器数据的主要方式.
  1. setState()
复制代码
视为请求而不是立即更新组件的命令。为了更好的感知性能,React 会延迟调用它,然后通过一次传递更新多个组件。
  1. setState()
复制代码
并不总是立即更新组件。它会批量推迟更新。这使得在调用
  1. setState()
复制代码
后立即读取
  1. this.state
复制代码
成为了隐患。为了消除隐患,请使用
  1. componentDidUpdate
复制代码
或者
  1. setState
复制代码
的回调函数(
  1. setState(updater, callback)
复制代码
),这两种方式都可以保证在应用更新后触发。
记住修改状态的三大原则:
不要直接修改 State
  1. state = { a: 10 }
  2. this.state.a = 100 // ❌
复制代码
state 的更新可能是异步的
  1. state = { a: 10 }
  2. this.setState({a: this.state.a + 1 })
  3. this.setState({a: this.state.a + 1 })
  4. this.setState({a: this.state.a + 1 })
  5. console.log(this.state.a) // 10
复制代码
state 的更新会被合并

1.4 this.setState()方法及其特点
  1. setState()
复制代码
会对一个组件的
  1. state
复制代码
对象安排一次更新。当 state 改变了,该组件就会重新渲染。
  1. setState()
复制代码
可以添加两个参数,
  1. setState()
复制代码
的第二个参数为可选的回调函数,它将在
  1. setState
复制代码
完成合并并重新渲染组件后执行

1.4.1 传递函数

参数一为带有形式参数的
  1. updater
复制代码
函数:
  1. this.setState((state, props) => stateChange[, callback] )
复制代码
  1. src/index.js
复制代码
  1. import React from 'react'
  2. import ReactDOM  from 'react-dom/client'

  3. // 引入时,后缀名可以省略,可以在webpack中配置
  4. // import App from './01-App-parent-child'
  5. // import App from './02-App-parent-child-value'
  6. // import App from './03-App-parent-child-value-default'
  7. // import App from './04-App-parent-child-value-default-type'
  8. // import App from './05-App-props-children'
  9. // import App from './06-App-mutiple-props-children'
  10. // import App from './07-App-mouse-tracker'
  11. // import App from './08-App-render-props'
  12. // import App from './09-App-state-es6'
  13. // import App from './10-App-state-es7'
  14. import App from './11-App-setState-function'

  15. const root = ReactDOM.createRoot(document.getElementById('root'))

  16. root.render(<App />)
复制代码
  1. src/11-App-setState-function.jsx
复制代码
  1. import React, { Component } from 'react';

  2. class App extends Component {
  3.   state = {
  4.     count: 100
  5.   }
  6.   render() {
  7.     return (
  8.       <div>
  9.         { this.state.count }
  10.         <button onClick={ () => {
  11.           this.setState((state, props) => {
  12.             console.log(state, props)
  13.             return {
  14.               count: state.count + 1
  15.             }
  16.           })
  17.           this.setState((state, props) => {
  18.             console.log(state, props)
  19.             return {
  20.               count: state.count + 1
  21.             }
  22.           })
  23.           this.setState((state, props) => {
  24.             console.log(state, props)
  25.             return {
  26.               count: state.count + 1
  27.             }
  28.           })
  29.         } }>加</button>
  30.       </div>
  31.     );
  32.   }
  33. }

  34. export default App
复制代码
  1. updater 函数中接收的 [code]state
复制代码
  1. props
复制代码
都保证为最新。updater 的返回值会与
  1. state
复制代码
进行浅合并。[/code]
1.4.2 传递对象
  1. src/index.js
复制代码
  1. import React from 'react'
  2. import ReactDOM  from 'react-dom/client'

  3. // 引入时,后缀名可以省略,可以在webpack中配置
  4. // import App from './01-App-parent-child'
  5. // import App from './02-App-parent-child-value'
  6. // import App from './03-App-parent-child-value-default'
  7. // import App from './04-App-parent-child-value-default-type'
  8. // import App from './05-App-props-children'
  9. // import App from './06-App-mutiple-props-children'
  10. // import App from './07-App-mouse-tracker'
  11. // import App from './08-App-render-props'
  12. // import App from './09-App-state-es6'
  13. // import App from './10-App-state-es7'
  14. // import App from './11-App-setState-function'
  15. import App from './12-App-setState-object'

  16. const root = ReactDOM.createRoot(document.getElementById('root'))

  17. root.render(<App />)
复制代码
  1. src/12-App-setState-object.jsx
复制代码
  1. import React, { Component } from 'react';
  2. // 为什么?
  3. // const obj = { a: 100 }
  4. // es6 中对象合并
  5. // const newObj = Object.assign(obj, {a: 100 + 1}, {a: 100 + 1}, {a: 100 + 1})
  6. // console.log(newObj) // { a: 101 }

  7. class App extends Component {
  8.   state = {
  9.     count: 10
  10.   }
  11.   render() {
  12.     return (
  13.       <div>
  14.         { this.state.count }
  15.         <button onClick={ () => {
  16.           this.setState({
  17.             count: this.state.count + 1
  18.           })
  19.           this.setState({
  20.             count: this.state.count + 1
  21.           })
  22.           this.setState({
  23.             count: this.state.count + 1
  24.           })
  25.           console.log(this.state.count)
  26.         } }>加</button>
  27.       </div>
  28.     );
  29.   }
  30. }

  31. export default App;
复制代码
  1. 这种形式的 [code]setState()
复制代码
是异步的,并且在同一周期内会对多个
  1. setState
复制代码
进行批处理,相当于[/code]
  1. Object.assign(
  2. prevState,
  3. {count: this.state.count + 1},
  4. {count: this.state.count + 1},
  5. ...
  6. )
复制代码
  1. 后调用的 [code]setState()
复制代码
将覆盖同一周期内先调用
  1. setState
复制代码
的值,因此商品数仅增加一次。如果后续状态取决于当前状态,建议使用 updater 函数的形式代替(前面案例已经实现)。或者在第二个参数中再继续操作。[/code]
  1. src/index.js
复制代码
  1. import React from 'react'
  2. import ReactDOM  from 'react-dom/client'

  3. // 引入时,后缀名可以省略,可以在webpack中配置
  4. // import App from './01-App-parent-child'
  5. // import App from './02-App-parent-child-value'
  6. // import App from './03-App-parent-child-value-default'
  7. // import App from './04-App-parent-child-value-default-type'
  8. // import App from './05-App-props-children'
  9. // import App from './06-App-mutiple-props-children'
  10. // import App from './07-App-mouse-tracker'
  11. // import App from './08-App-render-props'
  12. // import App from './09-App-state-es6'
  13. // import App from './10-App-state-es7'
  14. // import App from './11-App-setState-function'
  15. // import App from './12-App-setState-object'
  16. import App from './13-App-setState-callback'

  17. const root = ReactDOM.createRoot(document.getElementById('root'))

  18. root.render(<App />)
复制代码
  1. src/13-App-setState-callback.jsx
复制代码
  1. import React, { Component } from 'react';


  2. class App extends Component {
  3.   state = {
  4.     count: 10
  5.   }
  6.   render() {
  7.     return (
  8.       <div>
  9.         { this.state.count }
  10.         <button onClick={ () => {
  11.           this.setState({
  12.             count: this.state.count + 1
  13.           }, () => {
  14.             this.setState({
  15.               count: this.state.count + 1
  16.             }, () => {
  17.               this.setState({
  18.                 count: this.state.count + 1
  19.               })
  20.             })
  21.           })
  22.           console.log(this.state.count) // 10
  23.         } }>加</button>
  24.       </div>
  25.     );
  26.   }
  27. }

  28. export default App;
复制代码
  1. 思考题:
  2. 1.<a href="https://stackoverflow.com/a/48610973/458193" rel="external nofollow" target="_blank">何时以及为什么 setState() 会批量执行?</a>
  3. 2.<a href="https://github.com/facebook/react/issues/11527#issuecomment-360199710" rel="external nofollow" target="_blank">为什么不直接更新 this.state?</a>
复制代码
总结

通过本文的介绍,我们了解了
  1. state
复制代码
在 React 组件中的重要性,以及如何在 ES6 和 ES7 类组件中定义和使用
  1. state
复制代码
。同时,我们还探讨了正确更新
  1. state
复制代码
的方法,包括使用
  1. setState()
复制代码
方法时需要注意的事项。遵循这些最佳实践,可以帮助我们避免常见的陷阱,提高应用的性能和可靠性。
到此这篇关于React 组件中 State 的定义、使用及正确更新方式的文章就介绍到这了,更多相关React State 组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/javascript/331110r3m.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具