在路由傳遞參數
還記得我先前說過,「我們之後會在討論 params
時再深入探討」嗎?現在時機到了。
既然我們已經了解如何建立包含一組路由的堆疊導航欄,以及在這些路由之間導航,我們現在來看一下在導航到路由時,我們如何將資料傳遞到路由中。
這當中包含兩個部分
-
將參數傳遞到路由,方法是將它們放入物件中作為
navigation.navigate
函式的第二個參數:navigation.navigate('RouteName', { /* 參數在此處 */ })
-
在您的畫面元件中讀取參數:
route.params
。
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId, otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() =>
navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})
}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
初始參數
您可以將一些初始參數傳遞給畫面。如果在導覽到這個畫面時未指定任何參數,將會使用初始參數。它們與您傳遞的任何參數也會進行淺層合併。初始參數可以使用 initialParams
屬性指定
<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>
更新參數
畫面也可以更新其參數,就像它們可以更新其狀態一樣。navigation.setParams
方法讓您可以更新畫面的參數。參閱 setParams
API 參考 以取得更多詳細資料。
基本用法
navigation.setParams({
query: 'someText',
});
避免使用 setParams
更新畫面選項,例如 title
等。如果您需要更新選項,請使用 setOptions
。
將參數傳遞給前一個畫面
參數不只可以用於將一些資料傳遞到新畫面,還可以將資料傳遞到前一個畫面。例如,假設您有一個畫面,裡面有一個建立貼文按鈕,而建立貼文按鈕會開啟新畫面以建立貼文。在建立貼文後,您想要將貼文資料傳遞回前一個畫面。
要做到這一點,您可以使用 navigate
方法,如果畫面已經存在,它就會像 goBack
。您可以使用 navigate
將 params
傳遞回去以傳回資料
function HomeScreen({ navigation, route }) {
React.useEffect(() => {
if (route.params?.post) {
// Post updated, do something with `route.params.post`
// For example, send the post to the server
}
}, [route.params?.post]);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Create post"
onPress={() => navigation.navigate('CreatePost')}
/>
<Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
</View>
);
}
function CreatePostScreen({ navigation, route }) {
const [postText, setPostText] = React.useState('');
return (
<>
<TextInput
multiline
placeholder="What's on your mind?"
style={{ height: 200, padding: 10, backgroundColor: 'white' }}
value={postText}
onChangeText={setPostText}
/>
<Button
title="Done"
onPress={() => {
// Pass and merge params back to home screen
navigation.navigate({
name: 'Home',
params: { post: postText },
merge: true,
});
}}
/>
</>
);
}
在這裡,在您按下「完成」之後,主畫面的 route.params
將會更新為反映您在 navigate
中傳遞的貼文文字。
將參數傳遞給巢狀導覽器
如果您有巢狀導覽器,您需要以稍微不同的方式傳遞參數。例如,假設您在 Account
畫面中有一個導覽器,並想要將參數傳遞給其內的 Settings
畫面。然後,您可以按以下方式傳遞參數
navigation.navigate('Account', {
screen: 'Settings',
params: { user: 'jane' },
});
請參閱 巢狀導覽器,以取得關於巢狀的更多詳細資料。
參數中應該包含什麼
深入了解 params 中應填入哪種類型的資料非常重要。Params 就像螢幕選項一樣。它們應只包含能設定螢幕顯示內容的資訊。避免傳遞將顯示在螢幕上 itself 的完整資料(例如:傳遞使用者 ID 而不是使用者物件)。此外,避免傳遞多個螢幕會使用的資料,這些資料應儲存在全域儲存區。
你还可以像 URL 一樣思考 route 物件。如果你的螢幕有 URL,URL 中應該有哪些內容?Params 不應該包含你認為不應存在於 URL 中的資料。這通常表示你應保持載入畫面所需的最少資料。想像一下拜訪購物網站,當你看到產品清單時,URL 通常會包含類別名稱、排序類型、任何篩選條件等,但不會包含螢幕上顯示的實際產品清單。
例如, 假設你有一個 Profile
螢幕。當你導航至該螢幕時,你可能會試圖在 params 中傳遞使用者物件
// Don't do this
navigation.navigate('Profile', {
user: {
id: 'jane',
firstName: 'Jane',
lastName: 'Done',
age: 25,
},
});
這看起來很方便,讓你可以使用 route.params.user
存取使用者物件,而無需任何額外工作。
但是,這是一個反模式。資料,例如使用者物件,應該在你的全域儲存區中,而不是導航狀態中。否則,你在多個位置複製相同的資料。這可能會導致錯誤,例如即使使用者物件在導航後已變更,但個人資料螢幕仍顯示過時資料。
此外,透過深度連結或在網路上連結到螢幕時,會發生問題,因為
- URL 是螢幕的表示方式,因此也需要包含 params,亦即完整的使用者物件,這可能會使 URL 變得非常長且難以閱讀
- 由於使用者物件在 URL 中,因此有可能傳遞一個隨機使用者物件,代表一個不存在或個人資料資料不正確的使用者
- 如果沒有傳遞使用者物件,或格式不正確,可能會導致螢幕無法處理而當機
更好的方法是在 params 中僅傳遞使用者的 ID
navigation.navigate('Profile', { userId: 'jane' });
現在,你可以使用傳遞的 userId
從你的全域儲存區取得使用者。這消除了許多問題,例如過時的資料或有問題的 URL。
以下是一些 params 中應包含內容的範例
- ID,例如使用者 ID、項目 ID 等,例如
navigation.navigate('Profile', { userId: 'Jane' })
- 當你有項目清單時,用於排序、篩選資料等的 params,例如
navigation.navigate('Feeds', { sortBy: 'latest' })
- 分頁的時間戳記、頁碼或游標,例如
navigation.navigate('Chat', { beforeTime: 1603897152675 })
- 用於填寫螢幕上的輸入資料以便組成某樣東西,例如
navigation.navigate('ComposeTweet', { title: 'Hello world!' })
簡而言之,傳遞最少量的資料以識別 params 中的螢幕,在許多情況下,這表示僅傳遞物件的 ID 而不是傳遞完整的物件。保持你的應用程式資料與導航狀態分開。
摘要
navigate
和push
接受第二個選用引數,讓您傳遞參數給您導覽的路線。例如:navigation.navigate('RouteName', { paramName: 'value' })
.- 您可以在畫面中透過
route.params
讀取參數 - 您可以使用
navigation.setParams
更新畫面的參數 - 可透過
Screen
上的initialParams
prop 傳遞初始參數 - 參數應該包含顯示畫面的最小必要資料,不必更多