Reaguj-router-dom useParams () wewnątrz komponentu klasy

14

Próbuję załadować widok szczegółów na podstawie trasy reaktora-routera-dom, który powinien pobrać parametr URL (id) i użyć go do dalszego wypełnienia komponentu.

Moja trasa wygląda /task/:idi mój komponent ładuje się dobrze, dopóki nie spróbuję pobrać: id z adresu URL w następujący sposób:

    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;

Powoduje to następujący błąd i nie jestem pewien, gdzie poprawnie zaimplementować useParams ().

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

Dokumenty pokazują tylko przykłady oparte na komponentach funkcjonalnych, a nie oparte na klasach.

Dzięki za pomoc, jestem nowy, aby zareagować.

Jorre
źródło
6
Haki nie działają w komponentach opartych na klasie
Dupocas
@Dupocas ok, to ma sens. Co byś zasugerował, przepisz klasę do funkcji lub użyj klasy i spróbuj pobrać parametr url w inny sposób?
Jorre
Obie ważne alternatywy. Czy możesz napisać kod useParams? Może zmienisz to w HOC?
Dupocas,

Odpowiedzi:

35

Możesz użyć tego withRouterdo osiągnięcia. Wystarczy owinąć wyeksportowany sklasyfikowany komponent wewnątrz, withRoutera następnie można użyć, this.props.match.params.idaby uzyskać parametry zamiast używać useParams(). Można również uzyskać dowolny location, matchlub historyinformacji za pomocą withRouter. Wszystkie są przekazywane poniżejthis.props

Na twoim przykładzie wyglądałoby to tak:

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

Proste!

Michael Mayo
źródło
Proszę zaznaczyć poprawną odpowiedź.
Samuel Konat
3

Parametry przekazywane są przez rekwizyty na obiekcie dopasowania.

props.match.params.yourParams

źródło: https://redux.js.org/advanced/usage-with-react-router

Oto przykład z dokumentów niszczących rekwizyty w argumentach.

const App = ({ match: { params } }) => {
  return (
    <div>
      <AddTodo />
      <VisibleTodoList filter={params.filter || 'SHOW_ALL'} />
      <Footer />
    </div>
  )
}
znak
źródło
1

Ponieważ haki nie będą działać z komponentami opartymi na klasach, możesz zawinąć je w funkcję i przekazać właściwości:

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

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

Ale, jak powiedział @ michael-mayo, oczekuję, że withRouterjuż to działa.

SmujMaiku
źródło
0

Nie można wywołać hooka, takiego jak „useParams ()” z React.Component.

Najłatwiejszym sposobem, jeśli chcesz użyć haków i mieć istniejący reagować.Komponent jest utworzenie funkcji, a następnie wywołanie React.Component z tej funkcji i przekazanie parametru.

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;

Twoja zmiana trasy będzie nadal taka

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

wtedy będziesz mógł pobrać identyfikator z rekwizytów w swoim komponencie reagowania

this.props.taskId
RickWeb
źródło
0

Spróbuj czegoś takiego

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
źródło
-3

Za pomocą routera 5.1 można uzyskać identyfikator za pomocą:

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

i twój komponent niż może uzyskać dostęp do id:

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

const TaskDetail = () => {
  const {id} = useParams();
    return (
      <div>
        Yo {id}
      </div>
    );
};
t-reksio
źródło