React原生文本未更新



我试图在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

setTimeout调用缓存状态值,因此这些值永远不会更新。另一种方法是使用useEffect挂钩:来侦听状态变化

export default function App() {
const [sessionStarted, setSessionStarted] = useState(false);
const [breathDoing, setBreathDoing] = useState("STOP");
const getLabel = (status) => {
switch (status) {
case "IN":
return "We are breathing in we should breath out";
case "OUT":
return "We are breathing out we should breath in";
case "STOP":
return "We should stop breathing, yikes";
}
};
useEffect(() => {
const stateTransitions = {
STOP: "IN",
IN: "OUT",
OUT: "IN"
};
if (sessionStarted) {
const nextState = stateTransitions[breathDoing];
setTimeout(() => {
setBreathDoing(nextState);
}, 1000);
}
}, [sessionStarted, breathDoing]);
const breathSession = () => {
console.log("breathSession");
setBreathDoing("IN");
setSessionStarted(true);
};
const stopBreathSession = () => {
console.log("stopBreathSession");
setSessionStarted(false);
setBreathDoing("STOP");
};
const BreathOutput = (props) => {
return <div>{props.doing}</div>;
};
const handleSessionButton = () => {
if (sessionStarted) {
stopBreathSession();
} else {
breathSession();
}
};
return (
<>
<div>
<div level="1">
{sessionStarted ? (
<>
{getLabel(breathDoing)}
<BreathOutput doing={breathDoing} />
</>
) : null}
<button onClick={() => handleSessionButton()}>
{sessionStarted ? "stop" : "start"}
</button>
</div>
</div>
</>
);
}

背景信息:React-useState-为什么setTimeout函数没有最新的状态值?

您应该使用useState((而不是useRef((。要初始化breathingState,可以使用类似的语句

const [breathingState, setBreathingState] = useState('STOP');

然后,从函数breathIn((或breathOut((更新breathState,如下所示:

setBreathingState('IN');

setBreathingState('OUT')

分别。

在JSX中,只需将breathingState引用如下:

<BreathOutput doing={breathingState} />

React应该意识到需要进行重新渲染。

最新更新