使用 react-navigation 从 url 隐藏路由参数
Hide route params from the url with react-navigation
我正在将 ReactNative 移动应用程序改编为 ReactNative Web。该应用已完成 react-navigation
。
目前,每次我设置路由的参数(通过 navigate
或 setParams
)时,这些参数都会显示在 URL 中。我最终看起来很糟糕 URLs 像这样:
http://localhost:19006/me/undefined?user=%5Bobject%20Object%5D
那个或 URL 包含与用户无关的数据,通常看起来很乱。
有没有办法不在 URL 中显示路由参数?
您可以将组件需要的参数作为 prop 传递
像这样
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
然后在详细信息组件中
const { itemId , otherParam} = route.params;
或者,如果您使用 Redux/Mobx 或任何其他全局状态管理
您可以从那里提取数据,而不是通过 URL
然后借助 connect
或 useSelector
hooks
获取数据
如果您不想在 URL 中,如果 params 是存放此数据的合适位置,您应该 re-consider。如果您认为 URL 包含不相关的数据,则表明该数据不属于导航状态。
如果您直接从 URL 访问屏幕,它应该呈现与您以编程方式导航到它时相同的呈现方式。如果您在参数中传递某些内容,则意味着屏幕需要该信息才能正确呈现,如果您将其从 URL 中删除,则该信息将丢失。考虑到直接从 URL 打开页面是可能的,无论是在 Web 上还是使用深度 link。如果所需的数据不可用,那么它将无法工作。
在你的情况下,你似乎传递了一个完整的用户对象(也许不是,没有代码很难说)。理想情况下,这个对象应该在你的全局存储而不是参数中,你应该只在参数中传递用户 ID。然后,您应该使用该 ID 从全局存储中获取完整对象,或者如果尚未获取对象(如果需要)则触发数据获取。
您没有在问题中指定 React Navigation 的版本。在 v5 中,您可以自定义如何将参数字符串化为 URLs,以及如何使用 stringify
和 parse
选项将它们解析回来:
const linking = {
screens: {
Profile: {
path: 'user/:id',
parse: {
id: (id) => id.replace(/^@/, '')
},
stringify: {
id: (id) => `@{id}`,
},
},
},
};
这应该可以帮助您使 URL 看起来更漂亮,并处理参数不是简单字符串的情况。但是,您不能完全省略 URL 中的参数,因为它们是屏幕呈现所必需的数据。
更多详情:https://reactnavigation.org/docs/configuring-links#passing-params
绝对是正确的路径。只是想 post 这个解决方案,因为它是对问题的直接回答,即使不是最可取的。
import { getPathFromState} from "@react-navigation/native";
const linking = {
screens: {
...
},
getPathFromState(state, config){
let path = getPathFromState(state, config);
const index = path.indexOf("?")
if(index>=0){
path = path.substr(0, index);
}
return path;
}
};
注意:要使用此解决方案,您需要确保每个对象和函数参数都是可选的,否则如果您重新加载页面,将会出现错误。
我从 url 中删除了每个对象和函数,将此自定义 getPathFromState
添加到 linkingOptions:
const linking = {
config: {
screens: {
...
}
},
getPathFromState: (state, options) => {
const cleanState = {
...state,
routes: state.routes.map(route => {
if(!route.params) {
return route
}
const cleanParams = {}
for(const param in route.params) {
const value = route.params[param]
if(typeof value !== "object" && typeof value !== "function") {
cleanParams[param] = value
}
}
return {
...route,
params: cleanParams,
}
}),
}
return getPathFromState(cleanState, options) //imported from @react-navigation/native
},
}
我正在将 ReactNative 移动应用程序改编为 ReactNative Web。该应用已完成 react-navigation
。
目前,每次我设置路由的参数(通过 navigate
或 setParams
)时,这些参数都会显示在 URL 中。我最终看起来很糟糕 URLs 像这样:
http://localhost:19006/me/undefined?user=%5Bobject%20Object%5D
那个或 URL 包含与用户无关的数据,通常看起来很乱。
有没有办法不在 URL 中显示路由参数?
您可以将组件需要的参数作为 prop 传递
像这样
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
然后在详细信息组件中
const { itemId , otherParam} = route.params;
或者,如果您使用 Redux/Mobx 或任何其他全局状态管理
您可以从那里提取数据,而不是通过 URL
然后借助 connect
或 useSelector
hooks
如果您不想在 URL 中,如果 params 是存放此数据的合适位置,您应该 re-consider。如果您认为 URL 包含不相关的数据,则表明该数据不属于导航状态。
如果您直接从 URL 访问屏幕,它应该呈现与您以编程方式导航到它时相同的呈现方式。如果您在参数中传递某些内容,则意味着屏幕需要该信息才能正确呈现,如果您将其从 URL 中删除,则该信息将丢失。考虑到直接从 URL 打开页面是可能的,无论是在 Web 上还是使用深度 link。如果所需的数据不可用,那么它将无法工作。
在你的情况下,你似乎传递了一个完整的用户对象(也许不是,没有代码很难说)。理想情况下,这个对象应该在你的全局存储而不是参数中,你应该只在参数中传递用户 ID。然后,您应该使用该 ID 从全局存储中获取完整对象,或者如果尚未获取对象(如果需要)则触发数据获取。
您没有在问题中指定 React Navigation 的版本。在 v5 中,您可以自定义如何将参数字符串化为 URLs,以及如何使用 stringify
和 parse
选项将它们解析回来:
const linking = {
screens: {
Profile: {
path: 'user/:id',
parse: {
id: (id) => id.replace(/^@/, '')
},
stringify: {
id: (id) => `@{id}`,
},
},
},
};
这应该可以帮助您使 URL 看起来更漂亮,并处理参数不是简单字符串的情况。但是,您不能完全省略 URL 中的参数,因为它们是屏幕呈现所必需的数据。
更多详情:https://reactnavigation.org/docs/configuring-links#passing-params
import { getPathFromState} from "@react-navigation/native";
const linking = {
screens: {
...
},
getPathFromState(state, config){
let path = getPathFromState(state, config);
const index = path.indexOf("?")
if(index>=0){
path = path.substr(0, index);
}
return path;
}
};
注意:要使用此解决方案,您需要确保每个对象和函数参数都是可选的,否则如果您重新加载页面,将会出现错误。
我从 url 中删除了每个对象和函数,将此自定义 getPathFromState
添加到 linkingOptions:
const linking = {
config: {
screens: {
...
}
},
getPathFromState: (state, options) => {
const cleanState = {
...state,
routes: state.routes.map(route => {
if(!route.params) {
return route
}
const cleanParams = {}
for(const param in route.params) {
const value = route.params[param]
if(typeof value !== "object" && typeof value !== "function") {
cleanParams[param] = value
}
}
return {
...route,
params: cleanParams,
}
}),
}
return getPathFromState(cleanState, options) //imported from @react-navigation/native
},
}