react-router-dom useParams () dentro del componente de clase

14

Estoy tratando de cargar una vista de detalles basada en una ruta react-router-dom que debería tomar el parámetro de URL (id) y usarlo para completar el componente.

Mi ruta se ve /task/:idy mi componente se carga bien, hasta que trato de tomar el: id de la URL de esta manera:

    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;

Esto desencadena el siguiente error y no estoy seguro de dónde implementar correctamente useParams ().

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

Los documentos solo muestran ejemplos basados ​​en componentes funcionales, no basados ​​en clases.

Gracias por su ayuda, soy nuevo para reaccionar.

Jorre
fuente
66
Los ganchos no funcionan en componentes basados ​​en clase
Dupocas
@Dupocas ok, eso tiene sentido. ¿Qué sugeriría, reescribir la clase a una función o usar una clase e intentar tomar el parámetro url de otra manera?
Jorre
Ambas alternativas válidas. ¿Puedes publicar el código useParams? Tal vez convertirlo en un HOC?
Dupocas

Respuestas:

36

Puedes usar withRouterpara lograr esto. Simplemente envuelva su componente clasificado exportado dentro withRoutery luego puede usar this.props.match.params.idpara obtener los parámetros en lugar de usar useParams(). También puede obtener ningún location, matcho historyinformación utilizando withRouter. Todos pasan por debajothis.props

Usando su ejemplo se vería así:

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

¡Simple como eso!

Michael Mayo
fuente
Por favor marque esta respuesta correcta.
Samuel Konat
3

Los parámetros se transmiten a través de accesorios en el objeto de coincidencia.

props.match.params.yourParams

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

Aquí hay un ejemplo de los documentos que destruyen los accesorios en los argumentos.

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

Como los ganchos no funcionan con componentes basados ​​en clases, puede envolverlos en una función y pasar las propiedades:

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

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

Pero, como dijo @ michael-mayo, espero que esto sea lo withRouterque ya está funcionando.

SmujMaiku
fuente
0

No puede llamar a un enlace como "useParams ()" desde un React.Component.

La manera más fácil si desea usar ganchos y tener un react.component existente es crear una función y luego llamar al React.Component desde esa función y pasar el 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;

Su ruta de cambio seguirá siendo algo así como

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

entonces podrá obtener la identificación de los accesorios en su componente de reacción

this.props.taskId
RickWeb
fuente
0

Intenta algo como esto

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
fuente
-3

Con react router 5.1 puede obtener la identificación con lo siguiente:

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

y su componente que puede acceder a la identificación:

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

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