react-router-dom useParams () dentro do componente de classe

14

Estou tentando carregar uma exibição de detalhes com base em uma rota react-router-dom que deve pegar o parâmetro URL (id) e usá-lo para preencher ainda mais o componente.

Minha rota parece /task/:ide meu componente carrega bem, até eu tentar pegar o: id da URL da seguinte forma:

    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;

Isso dispara o seguinte erro e não tenho certeza onde implementar corretamente useParams ().

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

Os documentos mostram apenas exemplos baseados em componentes funcionais, não baseados em classe.

Obrigado pela sua ajuda, sou novo em reagir.

Jorre
fonte
6
Hooks não funcionam em componentes baseados classe
Dupocas
@ Dupocas ok, isso faz sentido. O que você sugeriria, reescrever a classe em uma função ou usar uma classe e tentar pegar o parâmetro url de outra maneira?
Jorre
Ambas as alternativas válidas. Você pode postar o código para useParams? Talvez transformá-lo em um HOC?
Dupocas 25/10/19

Respostas:

36

Você pode usar withRouterpara fazer isso. Simplesmente envolva seu componente classificado exportado dentro de withRoutere então você pode usar this.props.match.params.idpara obter os parâmetros em vez de usar useParams(). Você também pode obter qualquer location, matchou historyinformações usando withRouter. Todos são passados ​​sobthis.props

Usando seu exemplo, ficaria assim:

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

Simples assim!

Michael Mayo
fonte
Por favor, marque esta resposta correta.
Samuel Konat 17/04
3

Os parâmetros são transmitidos através de adereços no objeto de correspondência.

props.match.params.yourParams

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

Aqui está um exemplo dos documentos destruindo os objetos nos argumentos.

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

Como os ganchos não funcionam com componentes baseados em classe, você pode agrupá-lo em uma função e transmitir as propriedades:

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

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

Mas, como @ michael-mayo disse, espero que isso seja o que withRouterjá está acontecendo .

SmujMaiku
fonte
0

Você não pode chamar um gancho como "useParams ()" de um React.Component.

A maneira mais fácil, se você deseja usar ganchos e já possui um reat.component, é criar uma função, chame o React.Component dessa função e passe o parâmetro

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;

Sua rota de troca ainda será algo como

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

então você poderá obter o ID dos adereços no seu componente de reação

this.props.taskId
RickWeb
fonte
0

Tente algo assim

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;
Kesav
fonte
-3

Com o reag router 5.1, você pode obter o ID com o seguinte:

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

e seu componente que pode acessar o id:

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

const TaskDetail = () => {
  const {id} = useParams();
    return (
      <div>
        Yo {id}
      </div>
    );
};
t-reksio
fonte