我有这个状态的伴侣,在此当用户在线时,它会增加计数。我想将其更改为带有挂钩的功能组件,这在下面完成了
class App extends React.Component {
state = {
isOnline: true,
count: 1
}
handleOnline = () => {
if (!this.state.isOnline) {
this.setState({
count: this.state.count + 1
}, () => {
this.setState({ isOnline: !this.state.isOnline })
})
} else {
this.setState({ isOnline: !this.state.isOnline })
}
}
render() {
return (
<div className="App">
<h1>online ==> {this.state.isOnline ? 'Online' : 'Offline'}</h1>
<h1>count ==> {this.state.count}</h1>
<button onClick={this.handleOnline}>Toggle</button>
</div>
);
}
}
这是我转换为带有钩子的功能部件,
const App = () => {
const [isOnline, setIsOnline] = useState(true)
const [count, setCount] = useState(1)
const handleClick = () => {
if (!isOnline) {
setIsOnline(!isOnline)
setCount(count + 1)
} else {
setIsOnline(!isOnline)
}
}
return (
<div className="App">
<h1>online ==> {isOnline ? 'Online' : 'Offline'}</h1>
< h1 > count ==> {count}</h1>
<button onClick={handleClick}>Toggle</button>
</div>
)
}
在基于类的组件中,我读到不要一个接一个地使用setState,因此我在this.setState中使用了回调函数,如下所示:>
this.setState({
count: this.state.count + 1
}, () => {
this.setState({ isOnline: !this.state.isOnline })
})
现在,在功能组件中我一个接一个地使用setCount和setIsOnline很好吗?
const handleClick = () => {
if (!isOnline) {
setIsOnline(!isOnline)
setCount(count + 1)
} else {
setIsOnline(!isOnline)
}
我已经阅读过将useEffect用于回调,但是我得到的只是无限循环
。即使我的两个组件都能正常工作,也能达到预期的效果。我想知道我是否必须对回调使用useEffect或我在功能组件中带有钩子的实现是否正确???
我有这个状态的伴侣,在此当用户在线时,它会增加计数。我想将其更改为带有钩子的功能组件,这是我在类App扩展的React.Component之下完成的。
这种暗示是正确的,是的,我们不应该将一个状态设置为另一个状态,因为setState是异步工作的,但是由于您只设置了两个状态,所以就可以了。虽然您也可以保留一个状态对象,而不是保留两个单独的状态,即const [state,setState] = useEffect({count:1,isOnline:true});然后,您可以在一个setState中设置两个对象键。
同样在基于类的方法中,您使用了回调,但实际上并不需要,您可以使用单个setState来设置两个状态,即this.setState {count:this.state.count + 1,isOnline:!this.state.isOnline,})
一个接一个地调用设置状态是完全可以的,这是正确的做法:
const handleClick = () => {
if (!isOnline) {
setIsOnline(!isOnline)
setCount(count + 1)
} else {
setIsOnline(!isOnline)
}
}
状态是不同步更新的,这意味着状态变量isOnline
和count
直到组件重新渲染后才真正改变。调用setCount
和setIsOnline
不会更新这些变量,但会告诉React在下一个渲染器上进行更新。
这就是为什么你不能做这样的事情:
const handleClick = () => {
setCount(count + 1)
setCount(count + 1)
}
计数将增加1,而不是2。
为什么?
因为值count
尚未更新,因为我们必须等到重新渲染后才能更新它。这意味着count
在整个函数中具有相同的值-它永远不会改变。因此,您可以调用setCount(count + 1)
一百万次,并且该值只会增加1。这就是人们说你应该使用set state回调函数时的意思。
这是设置状态回调函数:
const handleClick = () => {
setCount(prev => prev + 1)
setCount(prev => prev + 1)
}
这将按预期工作,并且count
现在将增加2。
如果我们传递类似prev => prev + 1
的函数来设置状态,React会将
最新值传递给该函数。规则是:
每次使用旧状态值设置新状态值-传递函数以设置状态。
因此,尽管您当前的实现确实可行,但实际上您应该传递一个函数来设置count
上的状态,因为您依赖于先前的状态:
const handleClick = () => {
if (!isOnline) {
setIsOnline(!isOnline)
setCount(prev => prev + 1)
} else {
setIsOnline(!isOnline)
}
}
通常,您也应该对布尔值执行此操作,例如:setIsOnline(prev => !prev)
但是由于您在if语句中使用了isOnline
,因此此处不应该这样做,因为prev
的值可能与if
的值不同。
状态是不同步更新的,这意味着状态变量isOnline
和count
直到组件重新渲染后才真正改变。调用setCount
和setIsOnline
不会更新这些变量,但会告诉React在下一个渲染器上进行更新。