Reaction-router-dom: Неверный вызов ловушки. Хуки могут вызываться только внутри тела компонента функции - PullRequest
2 голосов
/ 17 октября 2019

Я пытаюсь вложить маршрут: у меня есть каталог продуктов в компоненте Catalog , который соответствует url "backoffice / catalog" .

Я хочу направить к Edition компоненту, если URL совпадает с "backoffice / catalog / edit" , но мне нужен компонент Edition быть потомком каталога для обмена реквизитом.

Я действительно не понимаю, почему не работает вложенный маршрут, пожалуйста, спасите меня! И не стесняйтесь сказать мне, если что-то не так с моим приложением, я хорошо знаю Javascript, но я начинаю с React: D

Вот мой компонент приложения:

import React from "react";
import { Route, Switch } from "react-router-dom";
import { Home } from "./components/Static/Home.js";
import { Dashboard } from "./components/Backoffice/Dashboard.js";
import { Catalog } from "./components/Backoffice/catalog/Catalog.js";
import { Login } from "./components/Login/Login.js";
import { Signup } from "./components/Signup/Signup.js";
import { PrivateRoute } from "./components/PrivateRoute.js";
import "./scss/App.scss";
import {Header} from "./components/Structure/Header";
import {BOHeader} from "./components/Structure/Backoffice/Header";
import {List} from "./components/Listing/List";

function App()
{
  return (
    <div className="App">
      <div className="App-content">
          <Switch>
              <Route path='/backoffice' component={BOHeader} />
              <Route path='/' component={Header} />
          </Switch>
          <Switch>
              <Route exact path='/' component={Home} />
              <Route exact path='/login' component={Login} />
              <Route exact path='/signup' component={Signup} />
              <Route path='/listing' component={List}/>
              <PrivateRoute exact path='/backoffice' component={Dashboard}/>
              <PrivateRoute exact path='/backoffice/catalog' component={Catalog}/>
          </Switch>
      </div>
    </div>
  );
}

export default App;

Вот мой компонент Каталога (маршрут выполняется в методе рендеринга:

import React from 'react';
import Data from '../../../Utils/Data';
import {Product} from './Product';
import {Edition} from './Edition';
import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link,
    useRouteMatch,
    useParams
} from "react-router-dom";

export class Catalog extends React.Component
{
    state = {
        title: '',
        products: [],
        editionProduct: null
    };

    obtainProducts = () =>
    {
        Data.products.obtain()
            .then(products => {this.setState({products: products});})
    };

    editProductHandler = product =>
    {
        this.setState({editionProduct: product});
    };

    saveProductHandler = product =>
    {
        Data.products.save(product).then(() => {
            this.state.products.map(item => {
                item = item._id === product._id ? product : item;
                return item;
            })
        });
    };

    deleteProductHandler = event =>
    {
        const productId = event.target.closest('.product-actions').dataset.productid;
        let products = this.state.products.filter(product => {
            return product._id !== productId;
        });
        this.setState({products: products}, () => {
            Data.products.remove(productId);
        });
    };

    displayProducts = () =>
    {
        return this.state.products.map(product => {
           return (
                <li key={product._id} className='catalog-item'>
                   <Product
                       deleteProductHandler={this.deleteProductHandler}
                       editProductHandler={this.editProductHandler}
                       data={product}
                   />
               </li>
            )
        });
    };


    componentWillMount()
    {
        this.obtainProducts();
    }

    render() {
        const Products = this.displayProducts();
        let { path, url } = useRouteMatch();
        return (
            <div className={this.state.editionProduct ? 'catalog edit' : 'catalog'}>
                <h1>Catalog</h1>
                <Switch>
                    <Route exact path={path}>
                        <ul className='catalog-list'>{Products}</ul>
                    </Route>
                    <Route path={`${path}/edit`}>
                        <Edition saveProductHandler={this.saveProductHandler} product={this.state.editionProduct} />
                    </Route>
                </Switch>
            </div>
        );
    }
}

Есть идеи?

1 Ответ

2 голосов
/ 17 октября 2019

Вы не можете использовать хуки внутри компонента Catalog, потому что это компонент класса. Таким образом, у вас есть два способа решения вашей проблемы:

  1. Перепишите свой компонент из класса в функционал.
  2. Не используйте useRouteMatch внутри Catalog компонента. Если вам нужно получить match данные внутри компонента, вам нужно использовать withRouter старшего компонента.

Поэтому, если вы выберете второй способ, вам понадобитсяобернуть ваш Catalog компонент в withRouter:

export default withRouter(Catalog);

Изменить одну строку в render функции с:

let { path, url } = useRouteMatch();

На:

const { path, url } = this.props.match;

И не забудьте изменить импорт вашего Catalog компонента, потому что теперь ваш компонент экспортируется по умолчанию.

...