React中能否基于当前路由设置变量匹配不同API接口发起请求?
实现方案
你可以选择以下两种方案实现需求,第一种完全贴合你期望的给Route加自定义endpoint属性的用法,第二种不需要修改现有上层路由、Home组件代码,只修改Contacts组件即可。
方案1:按你期望的自定义Route属性实现
该方案需要先抽离路由配置,将endpoint和路径绑定,透传到子组件即可。
- 抽离路由配置数组
const contactRoutes = [ { path: '/contacts/new', endpoint: '/newContacts' }, { path: '/contacts/list', endpoint: '/allContacts' }, { path: '/contacts/archived', endpoint: '/archivedContacts' }, { path: '/contacts/responsible/:responsible', endpoint: '/responsibleContacts/:responsible' }, { path: '/contacts/category/:category', endpoint: '/categoryContacts/:category' } ]
- 修改路由渲染逻辑
<BrowserRouter> <Switch> {contactRoutes.map(route => ( <Route key={route.path} path={route.path}> {/* 把路由配置传给Home组件 */} <Home routeConfig={route} /> </Route> ))} </Switch> </BrowserRouter>
- Home组件透传配置到Contacts
// Home组件内接收路由配置,传给Contacts function Home({ routeConfig }) { // 你的其他Home组件逻辑 return <Contacts routeConfig={routeConfig} /> }
- Contacts组件内处理endpoint动态参数
import { useParams } from 'react-router-dom' export function Contacts({ routeConfig }) { const params = useParams() // 替换endpoint模板里的动态参数为实际路由值 const endpoint = routeConfig.endpoint.replace(/:(\w+)/g, (_, key) => params[key]) const { isLoading, fetchContacts, contacts } = useContacts() useEffect(() => { fetchContacts(endpoint) }, [endpoint, fetchContacts]) // 剩余渲染逻辑和你原有代码一致 }
方案2:无需修改上层代码,Contacts内部做路径映射
如果你不想改动现有路由、Home组件的代码,可以直接在Contacts组件内部维护路径和endpoint的映射关系,自动匹配生成接口地址:
import { useLocation, useParams } from 'react-router-dom' // 维护路径模板和endpoint模板的映射 const pathEndpointMap = { '/contacts/new': '/newContacts', '/contacts/list': '/allContacts', '/contacts/archived': '/archivedContacts', '/contacts/responsible/:responsible': '/responsibleContacts/:responsible', '/contacts/category/:category': '/categoryContacts/:category', } export function Contacts() { const { pathname } = useLocation() const params = useParams() // 匹配当前路径对应的endpoint模板 const endpointTemplate = Object.entries(pathEndpointMap).find(([pathTemplate]) => { const matchRegex = new RegExp(`^${pathTemplate.replace(/:\w+/g, '\\w+')}$`) return matchRegex.test(pathname) })?.[1] // 替换动态参数得到最终接口地址 const endpoint = endpointTemplate.replace(/:(\w+)/g, (_, key) => params[key]) const { isLoading, fetchContacts, contacts } = useContacts() useEffect(() => { fetchContacts(endpoint) }, [endpoint, fetchContacts]) // 剩余渲染逻辑和你原有代码一致 }
内容的提问来源于stack exchange,提问作者Doougui
相关产品推荐
相关产品推荐

