05_为什么需要使用setState修改数据

243 阅读2分钟

为什么使用setState修改数据

为什么开发过程中不能通过直接修改state的值让页面更新

  • 因为直接修改state,React内部并不知道数据发生了变化
  • React并没有使用Vue2中的Object.defineProperty或者Vue3的Proxy来监听数据的变化
  • 所以必须通过setState来通知React数据发生了变化,需要对页面进行更新

setState 方法是从 React.Component 中继承的:

setState的三种用法

// 一.基本用法
this.setState({
	message: "你好,React"
})

// 二.setState可以传入一个回调函数
// 好处一: 回调函数会将之前的state和props传递进来
// 好处二: 可以在回调函数中编写新的state的逻辑
this.setState((state, props) => {
	// 1.编写一些对新的state处理逻辑
	// 2.可以获取之前的state和props值
	console.log(this.state.message, this.props)
	return {
		message: "你好啊, React"
	}
})

// 三.setState是异步的
// 如果希望在数据更新(合并)之后, 获取到对应的结果执行一些逻辑代码
// 可以在setState中传入第二个参数: callback
this.setState(
	{ message: "你好啊, React" }, 
	() => {
		console.log("++++++:", this.state.message)
	}
)

setState是异步更新的

  • setState的更新是异步的?

    • 下面代码的打结果是:Hello React
    • 课件setState是异步,所以不能在setState之后立刻拿到最新的state的值
changeMessage() {
	this.setState({
		messaged: '你好啊,React'
	})
	console.log(this.state.message) //Hello React
}
  • 为什么setState的设计是异步的?

  • setState设计为异步可以显著的提升性能

    • 如果每次调用setState都进行一次更新,意味着render函数会被频繁的调用,界面重新渲染,这样效率是很低的
    • 最好的方法就是获取到多个更新,进行批量更新
  • 如果同步更新了state,但是还没有执行render函数(render函数可能耗时较长),那么state和props不能保持同步, state和prop不能保持一致,会导致很多问题

  • 如何获取异步的结果

    • 方法一:setState(partialState, callback)的第二个参数,第二参数是一个回调函数,这个回调函数会在更新之后执行
    • 方法二:componentDidUpdate(prevProps, preState, snapshot)

setState一定是异步的吗?(React18之前)

分成两种情况:

  1. 在组件的生命周期或者React合成事件中,setState是异步
  2. 在setTimeout或者原生DOM事件中,setState是同步的
state = {
	message: 'HelloWorld',
}

changeMessage() {
	setTimeout(() => {
		this.setState({
			message: 'Hello React'
		})
		console.log(this.state.message)  //Hello React
	}, 0)
}

componentDidMount() {
	document.getElementById('btn').addEventListener('click', () => {
		this.setState({
			message: 'Hello React'
		})
		console.log(this.state.counter) //Hello React
	})
}

setState一定是异步的吗?(React18之后)

在React18之后,默认所有的操作都被放到了批处理中(异步处理)

github自动批处理相关:github.com/reactwg/rea…

如果希望代码可以同步执行(不需要批处理),需要使用flushSync

flushSync(() => {
	this.setState({message: 'Hello React'})
})
console.log(this.state.message) //Hello React