前言,我不是牛x的前端,但是这篇博客的知识,是从牛x的前端那儿偷师学来的!
牛 x 的前端是这么写:setState( 这里放一个函数 )
因为:
你以为的 state,其实不是现在新的 state 而是旧的 state
不太能理解我的意思?那往下看吧!
正常这么写
这是一个 +1 的 demo
class App extends React.Component {
constructor() {
super()
this.state = { n: 0 }
}
add() {
this.setState({ n: this.state.n + 1 })
}
render() {
return (
<div>
n: {this.state.n}
<button onClick={() => this.add()}>+1</button>
</div>
)
}
}
牛x的前端这么写
还是一个 +1 的 demo,注意 add(){}
class App extends React.Component {
constructor() {
super()
this.state = { n: 0 }
}
add() {
this.setState(state => {
return { n: state.n + 1 }
})
}
render() {
return (
<div>
n: {this.state.n}
<button onClick={() => this.add()}>+1</button>
</div>
)
}
}
对比
写法一: add() { this.setState({ n: this.state.n + 1 }) }
写法二: add() { this.setState(state => { return { n: state.n + 1 } }) }
那么,这两个写法是有什么区别呢?为什么 state() 里写一个函数就是牛x前端的写法了呢?
为什么不推荐写法一?
大部分时候,我们觉得,这个写法没有问题,因为点了 +1 按钮,一样可以正常加 1 啊!
但是!你在 加1 的时候,在代码下一行把 n 的值 log 出来看看,你会发现有问题 (具体什么问题,动动小手试一试)
add() { this.setState({ n: this.state.n + 1 }) }
console.log(this.state.n)
// UI 显示是 1,而 log 出来的居然是 0
复制代码
脑子:诶?那我点击 +1 按钮,就应该 log 出 加1后的值呀
现实:点击了 +1 按钮,打印出来的,却是旧的值!
因为这个 setState 不会马上去改变 state.n 的值,而是等一会儿再去改变,等谁呢?
等 console.log(this.state.n) 执行完了才改变 state.n 的值
所以说啊:setState 它是异步更新 state.n 的过程
所以,经常有人因为这个原因而造成 BUG
所以牛 x 写法是这样的
add() {
this.setState(state => { // 接受一个旧的 state
return { n: state.n + 1 } // 返回一个新的 state
})
}
还是一样,把 state.n log 出来:
这时候 log 出新的 n,总不会写成 console.log(state.n) 吧?
因为这个 state.n,它是旧的!
add() {
this.setState(state => { // 这是旧的 state
const n = state.n + 1 // 这个 n 是新的 n
console.log(n) // 然后把新的 n 打印出来
return { n } // 缩写,原来是return { n: n }
})
}
现在点击 +1 按钮,再看看 log,诶?是不是和 UI 同步了?
牛x写法也是异步执行的,但就是比第一种写法更好一点
所以,使用 state 的时候需要注意的一点就是:setState 不会马上去改变 state,最好使用函数去读新的值是会更好的
其实,简单的情况,可以用普通的方法写,但是稍微有一点复杂情况下,就一定一定要用 牛x 写法写,因为这种写法可以避免混淆 新旧的 state
总结
this.state.n += 1 无效?
其实 n 已经改变了,只不过 UI 不会自动更新而已
调用 setState 才会触发 UI 更新(异步更新)
因为 React 没有像 Vue 监听 data 一样监听 state
setState 会异步更新 UI
setState 之后,state 不会马上改变,马上读 state 会失败
所以更推荐的方式是 setState( 这里写函数 )
不推荐 this.setState(this.state)
React 希望我们不要修改旧 state(数据不可变)
这是一种函数式的理念
网友评论