Реагировать на использование маршрутизатора в библиотеке - невозможно использовать useHistory () - PullRequest
1 голос
/ 16 апреля 2020

У меня есть монорепо с несколькими приложениями и библиотеками, которое работает очень хорошо (на основе пряжи). В последнее время я провел некоторый рефакторинг и определил общий компонент, который я хотел «перенести» в библиотеку «общего достояния». Это содержит компонент, который использует ReactRouter.Route:

import React from 'react';
import { Route, useHistory } from 'react-router-dom';

export const AuthenticatedRoute = (props: Props): JSX.Element => {
   const history = useHistory(); // Crashes here

   ... do auth stuff ...

   useEffect(() => {
     if (!authenticated) {
        history.push(...);
     }
   }, []);

   return (
     <Route {...props}>
       {props.children}
     </Route>
   );
}

Этот компонент работает как шарм, когда содержал мое приложение реакции. Однако при извлечении в библиотеку commons во время выполнения происходит сбой со следующей ошибкой:

Uncaught TypeError: Cannot read property 'history' of undefined
    at useHistory (index.js:5914)
    at AuthenticatedRoute (index.js:9848)
    at renderWithHooks (react-dom.development.js:16260)
    at mountIndeterminateComponent (react-dom.development.js:18794)
    at beginWork$1 (react-dom.development.js:20162)
    at HTMLUnknownElement.callCallback (react-dom.development.js:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
    at invokeGuardedCallback (react-dom.development.js:440)
    at beginWork$$1 (react-dom.development.js:25780)
    at performUnitOfWork (react-dom.development.js:24695)

Я думаю, это как-то связано с тем, как библиотека / приложение ссылаются на библиотеку react-router-dom.

commons / package. json:

{
  "name": "commons",
  "version": "1.0.0",
  "main": "dist/index.js",
  "private": true,
  "dependencies": {
  },
  "peerDependencies": {
    "react-router-dom": "^5.1.2"
  }
}

app / package. json:

{
  "name": "app",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-router-dom": "^5.1.2",
    "commons": "1.0.0"
  }
}

app / app.ts:

import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';

export const App = (): JSX.Element => {
  return (
    <Router>
      <AuthenticatedRoute />
    </Router>
  );
};

Примечание. Если я прокомментирую useHistory, то в <Route> произойдет сбой, сказав, что он должен быть потомком <Router>.

То, что я пытался:

  • использовать peerDependencies, чтобы библиотека и приложение использовали один и тот же экземпляр реагирующего маршрутизатора
  • чистить и устанавливать пряжу несколько раз
  • дикие комбинации react-router & react-router-dom зависимостей

1 Ответ

0 голосов
/ 16 апреля 2020

withRouter - это НО C. Вы должны использовать его соответственно. из документации :

import { withRouter } from "react-router";

class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  };

  ...
}

const ShowTheLocationWithRouter = withRouter(ShowTheLocation);

Инициализация BrowserRouter выглядит нормально.

...