Экспорт `реакции-маршрутизатора` Перенаправление из общей библиотеки компонентов - PullRequest
8 голосов
/ 21 июня 2019

У меня есть общая (React) библиотека компонентов, которую я создаю.Есть компонент PrivateRoute, который я хочу включить.Однако, когда я импортирую компонент из библиотеки модулей в другое приложение, я получаю сообщение об ошибке:

Ошибка: сбой инварианта: вы не должны использовать вне

Компонент PrivateRoute оборачивает компонент react-router/Route логикой аутентификации и перенаправляет неаутентифицированные запросы на вход в систему:

библиотека компонентов

import { Route, Redirect } from 'react-router';
/* ... */

class PrivateRoute extends Component {
  /* ... */
  render() {
    const {
      component: Comp, authState, loginPath, ...rest
    } = this.props;

    return (
      <Route
        {...rest}
        render={props => authState === SIGNED_IN ? (
          <Comp {...props} />
        ) : (
          <Redirect
            to={{
              pathname: loginPath,
            }}
          />
        )}
      />
    );
  }
}

Затем я импортирую компонент в отдельный (React) проект:

create-реагировать-приложение

import { Router } from 'react-router';
import { PrivateRoute } from 'component-library';
/* ... */

class App extends Component {
  // "history" is passed in via props from the micro frontend controller.
  /* ... */

  render() {
    return (
      <Router history={this.props.history}>
        {/* ... */}
        <PrivateRoute path="/protected" component={ProtectedView} />
      </Router>
    );
  }
}

Это будет работать, как ожидается, если компонент PrivateRouteопределяется в приложении create-реакции-app .Однако перемещение этого компонента в разделяемую библиотеку приводит к ошибке.

Я попытался создать библиотеку с выводом веб-пакета libraryTarget, установленным на commonjs2 .Но я также попробовал umd .Я также попробовал с Rollup.Все с одинаковыми результатами.

webpack.config.js

module.exports = {
  //...
  output: {
    path: path.resolve(__dirname, 'dist/'),
    publicPath: '',
    filename: '[name].js',
    libraryTarget: 'commonjs2',
  },
  //...
};

Я предполагаю, что проблема заключается в построении библиотеки компонентов, поскольку выдается ошибка инварианта.когда Redirect не может найти RouterContext.Хотя библиотека собирается без ошибок, кажется, что импорт скомпилированного / встроенного кода является проблемой.

Может также быть два экземпляра React, вызывающих проблему с API контекста.Однако react-router не использует Context API.Он использует mini-create-react-context polyfill.

Есть мысли или идеи, как решить эту проблему?

Ответы [ 4 ]

2 голосов
/ 24 июня 2019

Вы должны импортировать роутер (при условии, что вы используете V4) из response-router-dom, например:

import { BrowserRouter as Router, Route, Link } from "react-router-dom";

В v4, response-router экспортирует основные компоненты и функции.Reaction-router-dom экспортирует компоненты, поддерживающие DOM, такие как (который отображает ) и (который взаимодействует с window.history браузера).

response-router-dom re-экспортирует все экспорты реагирующего маршрутизатора, поэтому вам нужно только импортировать из реактивного маршрутизатора в вашем проекте.

Ref: https://github.com/ReactTraining/react-router/issues/4648#issuecomment-284479720

0 голосов
/ 01 июля 2019

Я, наконец, обнаружил проблему, которая имела мало общего с react-router и больше с React. Я обнаружил, что эта ошибка будет отображаться только при локальной разработке, потому что component-library был связан через npm link.

Решение пришло из этого ответа: https://stackoverflow.com/a/38818358/715597

В моем случае решение состояло в том, чтобы связать React и React Router в библиотеке компонентов со ссылками на приложения React и React Router:

# link the component library
cd my-app
npm link ../component-library

# link its copy of React back to the app's React
cd ../component-library
npm link ../my-app/node_modules/react
npm link ../my-app/node_modules/react-router
0 голосов
/ 27 июня 2019

Не можете ли вы сделать это с помощью функции

if(authState === SIGNED_IN){
   return <Route
        {...rest}
        render={<Comp {...props} />
        />
}else{
   // here you can use window.location 
   // or 
   // render a different component (which shows unauthorized or something you want)
}
0 голосов
/ 26 июня 2019

вам нужно было только удалить зависимость «response-router-dom»: «5.0.0» из package.json, чтобы исправить ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...