【发布时间】:2021-05-02 09:02:44
【问题描述】:
我试图在 React Native 应用程序中模拟呼吸,呼吸的控制台日志似乎可以正常工作,但是屏幕上的文本永远不会更新。它只是坐在“IN”上
我是新来的反应和努力寻找解决方案。我尝试使用 useState 代替 useRef 来获取当前的呼吸状态,但它仍然没有更新,并且在使用 useState 时控制台无法按预期工作。
useRef 版本
import React from 'react'
import { useState, useRef, useEffect } from 'react'
import { SafeAreaView } from 'react-native'
import { Layout, Text, Button } from '@ui-kitten/components'
const HomeScreen = () => {
const [sessionStarted, setSessionStarted] = useState(false)
const breathDoing = useRef('STOP');
const doNext = () => {
console.log('doNext')
switch(breathDoing.current) {
case 'IN':
console.log('We are breathing in we should breath out')
breathOut()
break
case 'OUT':
console.log('We are breathing out we should breath in')
breathIn()
break
case 'STOP':
console.log('We should stop breathing, yikes')
break
}
}
const breathIn = () => {
console.log('In breath in')
breathDoing.current = 'IN'
setTimeout(() => {
doNext()
}, 1000)
}
const breathOut = () => {
console.log('In breath out')
breathDoing.current = 'OUT'
setTimeout(() => {
doNext()
}, 1000)
}
const breathSession = () => {
console.log('breathSession');
setSessionStarted(true)
breathIn()
}
const stopBreathSession = () => {
console.log('stopBreathSession');
setSessionStarted(false)
breathDoing.current = 'STOP'
}
const BreathOutput = (props) => {
return <Text>{props.doing}</Text>
}
const handleSessionButton = () => {
if (sessionStarted) {
stopBreathSession()
} else {
breathSession()
}
}
return (
<>
<SafeAreaView>
<Layout level="1">
{sessionStarted ?
<>
<BreathOutput doing={breathDoing.current} />
</>
: null}
<Button onPress={() => handleSessionButton()}>
{sessionStarted ? 'stop' : 'start'}
</Button>
</Layout>
</SafeAreaView>
</>
)
}
export default HomeScreen
控制台显示正确的输出:
We are breathing in we should breath out
In breath out
doNext
We are breathing out we should breath in
In breath in
doNext
We are breathing in we should breath out
In breath out
编辑
useState 版本:
const [sessionStarted, setSessionStarted] = useState(false)
const [breathDoing, setBreathDoing] = useState('STOP')
const doNext = () => {
console.log('doNext')
switch(breathDoing) {
case 'IN':
console.log('We are breathing in we should breath out')
breathOut()
break
case 'OUT':
console.log('We are breathing out we should breath in')
breathIn()
break
case 'STOP':
console.log('We should stop breathing, yikes')
break
}
}
const breathIn = () => {
console.log('In breath in')
setBreathDoing('IN')
setTimeout(() => {
doNext()
}, 1000)
}
const breathOut = () => {
console.log('In breath out')
setBreathDoing('OUT')
setTimeout(() => {
doNext()
}, 1000)
}
const breathSession = () => {
console.log('breathSession');
setSessionStarted(true)
breathIn()
}
const stopBreathSession = () => {
console.log('stopBreathSession');
setSessionStarted(false)
setBreathDoing('STOP')
}
const BreathOutput = (props) => {
return <Text>{props.doing}</Text>
}
const handleSessionButton = () => {
if (sessionStarted) {
stopBreathSession()
} else {
breathSession()
}
}
return (
<>
<SafeAreaView>
<Layout level="1">
{sessionStarted ?
<>
<BreathOutput doing={breathDoing} />
</>
: null}
<Button onPress={() => handleSessionButton()}>
{sessionStarted ? 'stop' : 'start'}
</Button>
</Layout>
</SafeAreaView>
</>
)
文本保持为“IN”
控制台输出
breathSession
In breath in
doNext
We should stop breathing, yikes
【问题讨论】:
-
每当
breathDoing.current的值发生变化时,react 不会重新渲染组件,因此值将保持不变。要解决此问题,我建议使用useState而不是useRef -
如果在返回前加上
console.log(breathDoing);,输出是什么?它是否正确地将值传递给 BreathOutput?
标签: reactjs react-native