跳至主要內容
版本:6.x

在路由傳遞參數

還記得我先前說過,「我們之後會在討論 params 時再深入探討」嗎?現在時機到了。

既然我們已經了解如何建立包含一組路由的堆疊導航欄,以及在這些路由之間導航,我們現在來看一下在導航到路由時,我們如何將資料傳遞到路由中。

這當中包含兩個部分

  1. 將參數傳遞到路由,方法是將它們放入物件中作為 navigation.navigate 函式的第二個參數: navigation.navigate('RouteName', { /* 參數在此處 */ })

  2. 在您的畫面元件中讀取參數: route.params

提示

我們建議您傳遞的可序列化為 JSON 格式的參數。這樣一來,您就能使用狀態持久性,而且您的畫面元件將具備實作深度連結的正確合約。

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。您可以使用 navigateparams 傳遞回去以傳回資料

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 存取使用者物件,而無需任何額外工作。

但是,這是一個反模式。資料,例如使用者物件,應該在你的全域儲存區中,而不是導航狀態中。否則,你在多個位置複製相同的資料。這可能會導致錯誤,例如即使使用者物件在導航後已變更,但個人資料螢幕仍顯示過時資料。

此外,透過深度連結或在網路上連結到螢幕時,會發生問題,因為

  1. URL 是螢幕的表示方式,因此也需要包含 params,亦即完整的使用者物件,這可能會使 URL 變得非常長且難以閱讀
  2. 由於使用者物件在 URL 中,因此有可能傳遞一個隨機使用者物件,代表一個不存在或個人資料資料不正確的使用者
  3. 如果沒有傳遞使用者物件,或格式不正確,可能會導致螢幕無法處理而當機

更好的方法是在 params 中僅傳遞使用者的 ID

navigation.navigate('Profile', { userId: 'jane' });

現在,你可以使用傳遞的 userId 從你的全域儲存區取得使用者。這消除了許多問題,例如過時的資料或有問題的 URL。

以下是一些 params 中應包含內容的範例

  1. ID,例如使用者 ID、項目 ID 等,例如 navigation.navigate('Profile', { userId: 'Jane' })
  2. 當你有項目清單時,用於排序、篩選資料等的 params,例如 navigation.navigate('Feeds', { sortBy: 'latest' })
  3. 分頁的時間戳記、頁碼或游標,例如 navigation.navigate('Chat', { beforeTime: 1603897152675 })
  4. 用於填寫螢幕上的輸入資料以便組成某樣東西,例如 navigation.navigate('ComposeTweet', { title: 'Hello world!' })

簡而言之,傳遞最少量的資料以識別 params 中的螢幕,在許多情況下,這表示僅傳遞物件的 ID 而不是傳遞完整的物件。保持你的應用程式資料與導航狀態分開。

摘要

  • navigatepush 接受第二個選用引數,讓您傳遞參數給您導覽的路線。例如: navigation.navigate('RouteName', { paramName: 'value' }).
  • 您可以在畫面中透過 route.params 讀取參數
  • 您可以使用 navigation.setParams 更新畫面的參數
  • 可透過 Screen 上的 initialParams prop 傳遞初始參數
  • 參數應該包含顯示畫面的最小必要資料,不必更多