类组件内部的react-router-dom useParams()


14

我正在尝试基于应获取URL参数(id)的react-router-dom路由加载详细信息视图,并使用该参数进一步填充组件。

我的路线看起来很像,/task/:id并且我的组件加载正常,直到我尝试像这样从URL抓取:id为止:

    import React from "react";
    import { useParams } from "react-router-dom";

    class TaskDetail extends React.Component {
        componentDidMount() {
            let { id } = useParams();
            this.fetchData(id);
        }

        fetchData = id => {
            // ...
        };

        render() {
            return <div>Yo</div>;
        }
    }

export default TaskDetail;

这会触发以下错误,我不确定在哪里正确实现useParams()。

Error: Invalid hook call. Hooks can only be called inside of the body of a function component.

该文档仅显示基于功能组件的示例,而不是基于类的示例。

感谢您的帮助,我是新来的人。


6
挂钩在基于类的组件中
不起作用

@Dupocas好的,这很有道理。您会提出什么建议,将类重写为函数或使用类,然后尝试以其他方式获取url参数?
Jorre

两种有效的选择。您可以为其发布代码useParams吗?也许把它变成一个HOC
Dupocas

Answers:


35

您可以withRouter用来完成此任务。只需将导出的分类组件包装在其中withRouter,然后就可以使用this.props.match.params.id来获取参数,而不必使用useParams()。您还可以得到任何locationmatchhistory通过使用信息withRouter。他们都被传进来this.props

使用您的示例,它看起来像这样:

    import React from "react";
    import { withRouter } from "react-router-dom";

    class TaskDetail extends React.Component {
        componentDidMount() {
            const id = this.props.match.params.id;
            this.fetchData(id);
        }

        fetchData = id => {
            // ...
        };

        render() {
            return <div>Yo</div>;
        }
    }

export default withRouter(TaskDetail);

就那么简单!


请将此答案标记为正确。
塞缪尔·科纳特

3

参数通过匹配对象上的道具传递下来。

props.match.params.yourParams

来源:https : //redux.js.org/advanced/usage-with-react-router

这是文档中销毁参数中道具的示例。

const App = ({ match: { params } }) => {
  return (
    <div>
      <AddTodo />
      <VisibleTodoList filter={params.filter || 'SHOW_ALL'} />
      <Footer />
    </div>
  )
}

1

由于钩子不能与基于类的组件一起使用,因此您可以将其包装在函数中并传递属性:

class TaskDetail extends React.Component {
    componentDidMount() {
        const { id } = this.props.params;
        // ...
    }
}

export default (props) => (
    <TaskDetail
        {...props}
        params={useParams()}
    />
);

但是,就像@ michael-mayo所说的那样,我希望这withRouter已经在执行。


0

您不能从React.Component调用钩子,例如“ useParams()”。

如果要使用钩子并具有现有的react.component,最简单的方法是创建一个函数,然后从该函数调用React.Component并传递参数。

import React from 'react';
import useParams from "react-router-dom";

import TaskDetail from './TaskDetail';

function GetId() {

    const { id } = useParams();
    console.log(id);

    return (
        <div>
            <TaskDetail taskId={id} />
        </div>
    );
}

export default GetId;

您的切换路线仍将是

<Switch>
  <Route path="/task/:id" component={GetId} />
</Switch>

那么您将可以从react组件中的props获取id

this.props.taskId

0

试试这个

import React from "react";
import { useParams } from "react-router-dom";

class TaskDetail extends React.Component {
let { id='' } = useParams();
    componentDidMount() {
        this.fetchData(id);
    }

    fetchData = id => {
        // ...
    };

    render() {
        return <div>Yo</div>;
    }
}

export default TaskDetail;

-3

使用React Router 5.1,您可以通过以下方式获取ID:

<Switch>
  <Route path="/item/:id" component={Portfolio}>
    <TaskDetail />
  </Route>
</Switch>

和您的组件将无法访问ID:

import React from 'react';
import { useParams} from 'react-router-dom';

const TaskDetail = () => {
  const {id} = useParams();
    return (
      <div>
        Yo {id}
      </div>
    );
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.