You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React高阶组件(HOC)中获取React Router方法?

解决React HOC中useLocation无法访问Router上下文的问题

问题描述

在React应用的高阶组件(HOC)中使用useLocation获取URL查询参数时,抛出以下错误:

Error: useLocation() may be used only in the context of a component.

相关代码

HOC组件代码

import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { getOrders } from "../../api/overview-controller";

const OrdersListHOC = (WrappedComponent) => {
    const orderListHOCComponent = () => {
        const search = useLocation().search;
        const limit = new URLSearchParams(search).get('limit') || 20;
        const [orders, setOrders] = useState([]);
        const [customerNumber, setCustomerNumber] = useState("");
        const [subcontractor, setSubcontractor] = useState("");

        useEffect (() => {
            fetchOrders()
        }, []);

        const fetchOrders = async() => {
            const searchFilter = {
                customerNumber,
                subcontractor,
                limit
            }
            const orders = await getOrders(searchFilter);
            setOrders(orders);
        }
        return (
            <div>
                <WrappedComponent orders={orders}/>
            </div>
        );
    }
    return orderListHOCComponent;
};

export default OrdersListHOC;

订单列表组件代码

const OrdersList = ({ orders }: props) => {
  return (<>
        {orders.map((order) => {
            return (<React.Fragment key={order.order.id}>
            <Grid container justifyContent={"center"} spacing={2}>
                <Grid item>
                    <Typography variant='subtitle1' mb={1/2}>Order number:</Typography>
                    <Typography variant='subtitle1' mb={1/2}>Customer name:</Typography>
                </Grid>
                <Grid item>
                    <Typography variant='h6'>{order.order.kind}{order.order.location.countryCode}{moment(order.order.orderDate, "YYYY-MM-DD").format("YY")}/{order.order.id}</Typography>
                    <Typography variant='h6'>{order.order.customerNumber.name}</Typography>
                </Grid>
            </Grid>
            <Divider light={false}/>
        </React.Fragment>)})}
  </>);
}

export default OrderListHOC(OrdersList);

解决方案

方案1:确保组件处于Router上下文范围内

useLocation是React Router的钩子,必须在<Router>(如BrowserRouter)组件的包裹下才能正常使用。检查你的应用路由配置,确保被HOC包装后的OrdersList组件是在Router内部渲染的。

示例路由配置:

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import OrdersList from './path/to/OrdersList';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/orders" element={<OrdersList />} />
      </Routes>
    </Router>
  );
}

方案2:拆分路由逻辑与HOC,提升复用性

如果需要让HOC在非路由场景下也能复用,可以将获取查询参数的逻辑从HOC中移出,放到处于Router上下文内的容器组件中,再将参数传递给HOC包装后的组件。

修改后的HOC

import React, { useEffect, useState } from 'react';
import { getOrders } from "../../api/overview-controller";

const OrdersListHOC = (WrappedComponent) => {
  const orderListHOCComponent = ({ limit = 20 }) => {
    const [orders, setOrders] = useState([]);
    const [customerNumber, setCustomerNumber] = useState("");
    const [subcontractor, setSubcontractor] = useState("");

    useEffect(() => {
      fetchOrders();
    }, []);

    const fetchOrders = async () => {
      const searchFilter = {
        customerNumber,
        subcontractor,
        limit
      };
      const orders = await getOrders(searchFilter);
      setOrders(orders);
    };

    return (
      <div>
        <WrappedComponent orders={orders} />
      </div>
    );
  };
  return orderListHOCComponent;
};

export default OrdersListHOC;

新增容器组件处理路由逻辑

import { useLocation } from 'react-router-dom';
import OrdersList from './OrdersList';
import OrdersListHOC from './OrdersListHOC';

const OrdersListContainer = () => {
  const search = useLocation().search;
  const limit = new URLSearchParams(search).get('limit') || 20;
  const WrappedOrdersList = OrdersListHOC(OrdersList);
  
  return <WrappedOrdersList limit={limit} />;
};

export default OrdersListContainer;

之后在路由配置中使用这个容器组件即可:

<Route path="/orders" element={<OrdersListContainer />} />

内容的提问来源于stack exchange,提问作者Profer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 12:53:16