Przekazywanie Reaktywnego routera dom Link do zewnętrznej biblioteki

10

Renderuję komponenty z mojej biblioteki wzorców zewnętrznych (node_modules). W mojej głównej aplikacji przekazuję moją Linkinstancję react-router-domdo komponentu bibliotek zewnętrznych w następujący sposób:

import { Link } from 'react-router-dom';
import { Heading } from 'my-external-library';

const articleWithLinkProps = {
    url: `/article/${article.slug}`,
    routerLink: Link,
  };

<Heading withLinkProps={articleWithLinkProps} />

W mojej bibliotece renderuje się Linktak:

const RouterLink = withLinkProps.routerLink;

<RouterLink
  to={withLinkProps.url}
>
  {props.children}
</RouterLink>

RouterLinkWydaje się do renderowania poprawnie, a nawet przejście do adresu URL po kliknięciu.


Mój problem polega na tym, że RouterLinkwygląda na to, że odłączono się od react-router-dominstancji mojej aplikacji . Kiedy klikam Heading, „twardo” nawiguje, odsuwa stronę, zamiast kierować ją bezproblemowo, jak Linkzwykle.

Nie jestem pewien, co mam teraz spróbować, aby umożliwić płynną nawigację. Każda pomoc lub rada będzie mile widziana, z góry dziękuję.

Edycja: Pokazuje, jak skonfigurowany jest mój router.

import React from 'react';
import { hydrate, unmountComponentAtNode } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import { ConnectedRouter } from 'react-router-redux';
import RedBox from 'redbox-react';
import { Route } from 'react-router-dom';
import { Frontload } from 'react-frontload';
import App from './containers/App';

import configureStore from './redux/store';
import withTracker from './withTracker';

// Get initial state from server-side rendering
const initialState = window.__INITIAL_STATE__;
const history = createBrowserHistory();
const store = configureStore(history, initialState);
const mountNode = document.getElementById('react-view');
const noServerRender = window.__noServerRender__;

if (process.env.NODE_ENV !== 'production') {
  console.log(`[react-frontload] server rendering configured ${noServerRender ? 'off' : 'on'}`);
}

const renderApp = () =>
  hydrate(
    <AppContainer errorReporter={({ error }) => <RedBox error={error} />}>
      <Provider store={store}>
        <Frontload noServerRender={window.__noServerRender__}>
          <ConnectedRouter onUpdate={() => window.scrollTo(0, 0)} history={history}>
            <Route
              component={withTracker(() => (
                <App noServerRender={noServerRender} />
              ))}
            />
          </ConnectedRouter>
        </Frontload>
      </Provider>
    </AppContainer>,
    mountNode,
  );

// Enable hot reload by react-hot-loader
if (module.hot) {
  const reRenderApp = () => {
    try {
      renderApp();
    } catch (error) {
      hydrate(<RedBox error={error} />, mountNode);
    }
  };

  module.hot.accept('./containers/App', () => {
    setImmediate(() => {
      // Preventing the hot reloading error from react-router
      unmountComponentAtNode(mountNode);
      reRenderApp();
    });
  });
}

renderApp();
danjones_mcr
źródło
Dlaczego nie <Link>przekazać komponentu do zewnętrznej biblioteki jako argumentu lub rekwizytów? pozwoliłoby to na większą elastyczność i czysty sposób obsługi nawigacji.
Ma'moun othman
Czy możesz pokazać, jak skonfigurowałeś router? Czy jest to przeglądarka, pamięć czy router statyczny?
zero298
@ zero298 - Zaktualizowane pytanie
danjones_mcr
@mamounothman - Tak właśnie się to robi, ale wydaje się, że wpływa na sposób, w jaki przechodzi do post-back.
danjones_mcr
Używasz przestarzałej biblioteki react-router-redux( github.com/reactjs/react-router-redux ), chyba że masz specjalne ograniczenia wymuszające stosowanie przestarzałych wersji bibliotek react-reduxi react-routerbibliotek, powinieneś rozważyć przejście na nowsze wersje, ponieważ może to rozwiązać problem ). Albo zrobić upgrade, czy należy podać dokładne wersje react, react-router-redux,react-redux a react-router-domprojekt jest obecnie za pomocą tak mamy szansę, aby znaleźć rozwiązanie łatanie.
GonArrivi

Odpowiedzi:

2

Zrekonstruowałem twój przypadek użycia w codesandbox.io i „przejście” działa dobrze. Więc może sprawdzenie mojej implementacji może ci pomóc. Jednak zamieniłem import biblioteki na import pliku, więc nie wiem, czy to decydujący czynnik, dlaczego nie działa bez przeładowania całej strony.

Nawiasem mówiąc, co dokładnie rozumiesz przez „płynnie”? Czy są elementy, które pozostają na każdej stronie i nie należy ich ponownie ładować po kliknięciu linku? To tak, jak zaimplementowałem to w piaskownicy, gdzie statyczny obraz pozostaje na górze każdej strony.


Sprawdź piaskownicę .

To jest example.jsplik

// This sandbox is realted to this post https://stackoverflow.com/q/59630138/965548

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import { Heading } from "./my-external-library.js";

export default function App() {
  return (
    <div>
      <img
        alt="flower from shutterstock"
        src="https://image.shutterstock.com/image-photo/pink-flowers-blossom-on-blue-600w-1439541782.jpg"
      />
      <Router>
        <Route exact={true} path="/" render={Welcome} />
        <Route path="/article/coolArticle" component={CoolArticleComponent} />
      </Router>
    </div>
  );
}

const Welcome = () => {
  const articleWithLinkProps = {
    url: `/article/coolArticle`,
    routerLink: Link
  };

  return (
    <div>
      <h1>This is a super fancy homepage ;)</h1>
      <Heading withLinkProps={articleWithLinkProps} />
    </div>
  );
};

const CoolArticleComponent = () => (
  <div>
    <p>This is a handcrafted article component.</p>
    <Link to="/">Back</Link>
  </div>
);

A to jest my-external-library.jsplik:

import React from "react";

export const Heading = ({ withLinkProps }) => {
  const RouterLink = withLinkProps.routerLink;
  return <RouterLink to={withLinkProps.url}>Superlink</RouterLink>;
};
New3D
źródło
Cześć, wielkie dzięki za odpowiedź! Wydaje się, że problem występuje tylko przy przejściu przez node_modules.
danjones_mcr