在类组件内部使用 Params()

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

我的路线看起来像 /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.

文档只显示基于函数组件的示例,而不是基于类的示例。

104167 次浏览

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

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>
)
}

版本 < = 5:

您可以使用 withRouter来实现这一点。只需将导出的分类组件包装在 withRouter中,然后就可以使用 this.props.match.params.id获取参数,而不必使用 useParams()。您也可以得到任何 locationmatch,或 history信息使用 withRouter。它们都是在 this.props下通过的

用你的例子看起来是这样的:

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


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);

就这么简单!

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

如果您希望使用 hook 并拥有现有的 React.Component,最简单的方法是创建一个函数,然后调用 React。组件并传递参数。

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>

然后你就可以从你的反应组件的道具中得到 id

this.props.taskId

由于 hook 不能与基于类的组件一起工作,所以可以将它包装在函数中并传递属性:

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


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

但是,就像@michael-mayo 说的,我希望这是 withRouter已经在做的。

反应路线 V5

可以使用 withRouterqueryString以 JSON 的形式读取和处理查询参数,如下所示:

import React from "react";
import { withRouter } from "react-router";
import queryString from 'query-string';
    

class MyComponent extends React.Component {
componentDidMount() {
const params = queryString.parse(this.props.location.search);
console.log('Do something with it', params);
}


render() {
return <div>Hi!</div>;
}
}


export default withRouter(MyComponent);

在 response-router-dom v6中,没有像 路由器这样的钩子,因此我建议您将基于类的组件转换为函数组件,以便在组件中使用 UseParams钩子,否则您可以创建一个高阶组件来传递基于类的组件。

反应路线 V6

我的朋友们,我试着在课堂上使用,但是我找不到任何相关的文件。因此,经过几个小时的搜索和努力,这是(在功能上)。现在(也就是我写这篇文章的时候)关于 v6的资源是有限的。但是 < v6有很多。

这里我使用 UseState使用效果UseParams公理

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';


const Post = () => {
let { post_id } = useParams();
const [posts, setPosts] = useState({ post: null, countSecrets: 0, ui: '' });


useEffect(() => {
if (posts.countSecrets === 0) {
const doAxe = (a) => {
axios.get('https://jsonplaceholder.typicode.com/posts/' + post_id)
.then((res) => {
setPosts(s => ({ ...s, value: res.data }));
doUI(res.data)
// console.log(res.data)
});
}
setPosts(s => ({ ...s, countSecrets: s.countSecrets + 1 }));
doAxe()
}
}, [posts, post_id]);
let doUI = (x) => {
// console.log('x' + x.title)
const finalPost = (x !== null) ? (
<div className="post">
<h4 className="center">{x.title}</h4>
<p>{x.body}</p>
</div>
) : (
<div className="center">Loading posts...</div>
);
setPosts(s => ({ ...s, ui: finalPost }));
}
return (
<div className="container">
{posts.ui}
</div>
);
}


export default Post;

注意: 我遇到了 使用效果循环,我用钥匙阻止了它。

希望: 这可以帮助某人!

参考文献:

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


function withParams(Component) {
return props => <Component {...props} params={useParams()} />;
}




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


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


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


export default withParams(TaskDetail);

SmujMaiku 是正确的! ! ! 他的回答完美工作。这是如何工作今天与反应路由器 v6

enter code here
   

import React ,{Component} from 'react'
import {  useParams } from "react-router-dom";
import PokeDescription from '../components/PokeDescription'


class PokeInfoConteiner extends Component{


render(){
    

let urlPokemon= "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/"
    

    

const {idPokemon} = this.props.params
console.log(idPokemon)


return(
        

<div>
<PokeDescription pokeImage={`${urlPokemon}${idPokemon}.png?raw=true`}/>
<p>{}</p>
            

</div>


)


}

}

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

在 React 路由器 V6中 :

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


/* This is a higher order component that
*  inject a special prop   to our component.
*/
function withRouter(Component) {
function ComponentWithRouter(props) {
let params = useParams()
return <Component {...props} params={params} />
}
return ComponentWithRouter
}
class TaskDetail extends React.Component {
state={
id : ""
}
componentDidMount() {
this.setState({
id : this.props.params.id
})
}
static getDerivedStateFromProps(nextProps) {
return {
id : nextProps.params.id
}
}
fetchData = id => {
// ...
};


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




const HOCTaskDetail = withRouter(TaskDetail);


export default HOCTaskDetail;


在 response-router-dom-v6中,你可以很容易地在函数组件中使用 useParams () ,但是当它到达类组件时,你必须创建 HOC (高阶组件) ,因为钩子不支持类组件:

import { useNavigate, useParams } from "react-router-dom";


export const withRouter = (WrappedComponent) => (props) => {
const params = useParams();
const navigate = useNavigate();


return <WrappedComponent {...props} params={params} navigate={navigate} />;
};

然后从 HOC 导出您的组件,并将您的组件作为参数给出:

export default withRouter(YourComponentName);

之后,您可以轻松地访问与 this.props.params.id的网址标识,您可以导航到其他组件与 this.props.navigate("/YourPath")

正如您所知道的 useParams ()是一个用于 response-router-dom 的挂钩。 您不能在组件 DidMount ()或 useEffect ()中使用它,因为它们都是在 React 生命周期的安装阶段(即组件呈现之后)调用的方法。 你有办法了: 在组件 DidMount ()之外创建或定义另一个函数来定义 useParams,然后在组件 DidMount 中调用它。 知道一切都会好起来的。

这是我的工作范例。 :)

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


function withParams(Component) {
return (props) => <Component {...props} params={useParams()} />;
}


class ProductDetails extends Component {
handleSave = () => {
// Navigate to /products
};


render() {
return (
<div>
<h1>Product Details - {this.props.params.id}</h1>
<button onClick={this.handleSave}>Save</button>
</div>
);
}
}


export default withParams(ProductDetails);

钩子只对功能性组件起作用, 你必须让这个组件成为一个功能性组件

通过创建一个包装函数来修复

我需要使用 response-router-dom v6从 index.js 传递 params 到我的 SaxjaxApp.js。 在 v6中,Switch已经改为 Routes

我得到了 useParams 与类组件的工作,遵循 Mohamed MAZEK 的想法在后20使用一个包装函数。

我需要访问网址的 sessionId部分时,它是可用的。

localhost:3000/shared/123XYZId 我需要 123XYZId那部分。

请注意这一行: 下面 index.js 中的 <Route path="/shared/:sessionId" element={<SaxjaxAppWrapper />} />

:sessionId表示 useParams有一个名为 sessionId的属性,可以通过以下方式访问:

从一个功能组件的 const {sessionId} = useParams()

在 index.js 文件中,我这样做了:

import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter, Route, Routes } from "react-router-dom";


import "./styles/style.scss";


import SaxjaxAppWrapper from "SaxjaxAppWrapper";
import SaxjaxApp from "./SaxjaxApp";


const container = document.getElementById("root");
const root = ReactDOM.createRoot(container);
//INFO: to learn about react-roue-dom v6 https://reactrouter.com/en/v6.3.0/upgrading/v5


root.render(
// <React.StrictMode>
<BrowserRouter>
<Routes>
<Route path="/shared/:sessionId" element={<SaxjaxAppWrapper />} />
<Route path="/" element={<SaxjaxApp />} />
</Routes>
</BrowserRouter>
// </React.StrictMode>
);


这一行 <Route path="/shared/:sessionId" element={<SaxjaxAppWrapper />} />调用我的包装函数,而默认路径 /只调用类组件。

我不得不创建一个单独的文件来保存包装功能,我不知道为什么:

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

function SaxjaxAppWrapper() {


//I use the params here and store them to pass as props
let { sessionId } = useParams();


return (
//I pass the sessionId from the url params as a prop to my SaxjaxApp class component here
<SaxjaxApp sessionId={sessionId} />
);
}
    

export default SaxjaxAppWrapper;

我的类组件:

import React, { Component } from "react";
import "./styles/style.scss";


class SaxjaxApp extends Component {
state = {
octave: 4,
};


constructor(props) {
super(props);
//... initialise stuff
}


//... a lot of methods


render() {
//Access the param here
const { sessionId } = this.props;
<>
<div>
keybordId={sessionId ? sessionId : "no id was passed"}
</div>
</>


);
}
}


export default SaxjaxApp;