我在反應方面的知識相當不存在,但我正在學習。我在學校學習了基礎知識,使用類組件(經典的 React),但現在我正在深入研究 Hooks API(主要是因為我發現它更容易學習和管理,盡管似乎有更多關于異步行為的技巧) . 所以我的問題可能看起來很愚蠢。
我在同一主題上找到了有關 setState 行為的執行緒,但這是關于類組件的。
在我當前的應用程式中,我嘗試使用事件處理程式設定三種不同的狀態。似乎最后一個狀態是立即設定的,而其他兩個狀態在更改為實際值之前暫時保持未定義狀態。我正在使用 React-Native 組件進行移動開發,因此您將在代碼中看到諸如<SafeAreaView>.
export default App = () => {
const [ destLong, setDestLong ] = useState();
const [ destLat, setDestLat ] = useState();
const [ startNav, setStartNav ] = useState(false);
const [ locations, setLocations ] = useState([
{
name: 'IKEA',
long: '-74.00653395444186',
lat: '40.68324646680103',
},
{
name: 'JFK Intl. Airport',
long: '-73.78131423688552',
lat: '40.66710279890186',
},
{
name: 'Microcenter',
long: '-74.00516039699959',
lat: '40.67195933297655',
}
]);
const startNavigation = (goinglong, goinglat) => {
setDestLong(goinglong);
setDestLat(goinglat);
setStartNav(true);
}
return (
<SafeAreaView style={styles.container}>
{ startNav ?
<MapView
destLong = {destLong}
destLat = {destLat}
/>
:
<View style={styles.buttonContainer}>
<ScrollView>
{
locations.map((location, i) => {
return(
<Card
style={styles.card}
key={i}
title={ location.name }
iconName="home"
iconType="Entypo"
description={ location.long ", " location.lat }
onPress={() => startNavigation(location.long, location.lat)}
/>
);
})
}
</ScrollView>
</View>
}
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
buttonContainer: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center'
},
logo: {
width: '50%',
height: '50%',
resizeMode: 'contain'
},
card: {
marginBottom: 10,
}
});
This throws an error, because MapView is expecting destLong and destLat to render properly. When I console log inside my startNavigation function, it seems that it immediately updates the state for startNav to true onPress, but destLong and destLat remain undefined for a few cycles before being set.
I've tried a different approach like this:
useEffect(() => {
setStartNav(true);
}, [destLong]);
const startNavigation = (goinglong, goinglat) => {
setDestLong(goinglong);
setDestLat(goinglat);
}
But it just crashes the app (my guess is infinite loop).
I've also tried removing the startNav state altogether and rendering <MapView> on destLong like this
{ destLong ?
<MapView
destLong = {destLong}
destLat = {destLat}
/>
:
<View style={styles.buttonContainer}>
...
</View>
}
But that did not work either.
Which brings me to this question: does the Hooks API respect the order of setState, or is each other carried out asynchronously? From my understanding it's the latter. But then, how do you handle this behavior?
uj5u.com熱心網友回復:
我也在這里添加我的評論,因為我無法在上面的評論中添加正確的格式。
通過設定狀態useState實際上是異步的,或者更確切地說,狀態更改被排隊,然后在重新渲染后回傳其新值。這意味著無法保證狀態的設定順序。它們將按順序觸發,但它們的設定順序可能不同。
您可以在此處閱讀更多資訊:https : //dev.to/shareef/react-usestate-hook-is-asynchronous-1hia以及此處https://blog.logrocket.com/a-guide-to-usestate- in-react-ecb9952e406c/#reacthooksupdatestate
在你的情況下,我會使用useState并useEffect喜歡這個:
useEffect(() => {
if(destLong && destLat && !startNav) {
setStartNav(true);
}
}, [destLong, destLat, startNav]);
const startNavigation = (goinglong, goinglat) => {
setDestLong(goinglong);
setDestLat(goinglat);
}
話雖如此,我認為您可以通過完全省略 startNav 狀態并更新條件渲染來進一步簡化代碼:
{ (destLat && destLong) ?
<MapView
destLong = {destLong}
destLat = {destLat}
/>
:
<View style={styles.buttonContainer}>
...
</View>
}
以上應該具有相同的效果,因為您有兩個未定義的狀態開始,并且當它們都被定義時,您想要渲染某些東西并使用它們的值。
如果您想再次顯示選項,您可以通過執行setDestLat(undefined)和操作再次將狀態設定為未定義setDestLong(undefined)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/359562.html
標籤:reactjs react-native react-hooks
上一篇:如何避免布局與狀態欄重疊?
