第一次浏览Test component
时,一切正常。 React Navigation 5用于导航到Results
页面,然后导航回到Test component
。但是,尽管我通过timerIsRunning
正确地收到了route.params
道具,但并未像我期望的那样设置并传递给<Timer>
。
我是否误解了它的工作原理?
测试组件(已删除)
export const Test = ({ navigation, route }) => {
const { timed, category, minutes, timerIsRunning } = route.params; // data is received correctly
const [timerRunning, setTimerRunning] = React.useState(timerIsRunning); // this works the first time it's navigated to
return (
<View style={{ flex: 1, margin: 10 }}>
<ScrollView>
{timed ? <Timer seconds={minutes*60} timerRunning={timerRunning} /> : null} // timer component called here
</ScrollView>
<Button
onPress={() => {
setResponseDetails({ answered: false, index: null });
setActiveIndex(0);
setStoredResponses([]);
setTimerRunning(false); // this correctly stops the timer
navigation.navigate('Results', { // and navigates to the Results page
data: storedResponses,
category: category,
timed: timed,
minutes: minutes,
});
}}
disabled={!responseDetails.answered}
style={styles.button}
>
<Text>Results</Text>
<Icon name="arrow-dropright" />
</Button>
)
</View>
);
};
结果页面(摘要)
export const Results = ({ navigation, route }) => {
const { category, data: testData, timed, minutes } = route.params;
return (
<View>
<Button
onPress={() =>
navigation.navigate('Test', { // Navigates back to test
timed: timed,
minutes: minutes,
category: category,
timerIsRunning: true // Correctly passes this prop, and is received in the Test component
})
}
>
<Icon name="arrow-back" />
<Text>Try the {category} test again</Text>
</Button>
</View>
);
};
答案 0 :(得分:0)
您是否尝试过将timerActive
添加为对第二个useEffect的依赖项之一?
React.useEffect(() => {
if (timeLimit > 0 && timerActive) {
setTimeout(() => {
// console.log('startTime, ', timeLimit);
settimeLimit(timeLimit - 1);
}, 1000);
}
if (timeLimit === 0 && timerRunning || !timerRunning) {
console.log('done');
}
}, [timeLimit, timerActive]);
答案 1 :(得分:0)
以下是一个工作计时器的示例,该计时器需要几秒钟的时间,并且timerRunning作为道具,如果需要任何帮助,请告诉我。您可以更新问题或添加有效的代码段。
const pad = (num) => `0${String(num)}`.slice(-2);
//moved formatTime out of the component
const formatTime = (timeLimit) => {
let displaySeconds = timeLimit % 60;
let minutes = Math.floor(timeLimit / 60);
//clean up formatting number
return `${pad(minutes)}:${pad(displaySeconds)}`;
};
const Timer = ({ seconds, timerRunning }) => {
const [timeLimit, settimeLimit] = React.useState(seconds);
//removed timerActive as it's a copy of timerRunning
React.useEffect(
() => {
if (timerRunning) {
//changed this to a interval and cancel it
// when timeLimit or timerRunning changes
let interval;
if (timerRunning) {
interval = setInterval(() => {
//using callback to get current limit value
// prevent using stale closure or needless
// dependency
settimeLimit((timeLimit) => {
//do the check here so timeLimit is not
// a dependency of this effect
if (timeLimit !== 0) {
return timeLimit - 1;
}
//do not keep running the interval
// if timeLimit is 0
clearInterval(interval);
return timeLimit;
});
}, 1000);
}
//clean up function will end interval
return () => clearInterval(interval);
}
},
//re run if seconds or timerRunning changes
[seconds, timerRunning]
);
//set local timeLimit again when seconds change
React.useEffect(() => settimeLimit(seconds), [seconds]);
return <div> {formatTime(timeLimit)}</div>;
};
function App() {
const [seconds, setSeconds] = React.useState(10);
const [running, setRunning] = React.useState(false);
return (
<div>
<div>
<label>
run timer
<input
type="checkbox"
checked={running}
onChange={() => setRunning((r) => !r)}
/>
</label>
<div>
<label>
<select
onChange={(e) =>
setSeconds(Number(e.target.value))
}
value={seconds}
>
<option value={1}>1</option>
<option value={10}>10</option>
<option value={100}>100</option>
<option value={1000}>1000</option>
</select>
</label>
</div>
</div>
<Timer seconds={seconds} timerRunning={running} />
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 2 :(得分:0)
好的,实际上我已经解决了-使用React Navigation 5.x,您可以使用route.params
中的useEffect
来触发动作。我结束了:
React.useEffect(() => {
setTimerRunning(timerIsRunning);
}, [route.params]);