Passando il link di reazioni-router-dom nella libreria esterna


10

Sto eseguendo il rendering dei componenti dalla mia libreria di pattern esterna (node_modules). Nella mia app principale, sto passando la mia Linkistanza dal react-router-domcomponente delle mie librerie esterne in questo modo:

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

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

<Heading withLinkProps={articleWithLinkProps} />

Nella mia libreria, il rendering è il seguente Link:

const RouterLink = withLinkProps.routerLink;

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

La RouterLinksembra rendere correttamente, e anche naviga all'URL quando si fa clic.


Il mio problema è che RouterLinksembra che si sia staccato dall'istanza della mia app react-router-dom. Quando clicco Heading, naviga "duramente", postando indietro la pagina invece di instradarla senza problemi come Linkfarebbe normalmente.

Non sono sicuro di cosa provare a questo punto per consentirgli di navigare senza problemi. Qualsiasi aiuto o consiglio sarebbe apprezzato, grazie in anticipo.

Modifica: mostra come è impostato il mio 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();

Perché non far <Link>passare il componente al tuo lib esterno come argomento o oggetti di scena? ciò consentirebbe maggiore flessibilità e un modo pulito di gestire la navigazione.
ROOT

Puoi mostrare come hai configurato il tuo router? È un browser, memoria o router statico?
zero298

@ zero298 - Domanda aggiornata
danjones_mcr

@mamounothman - Ecco come viene attualmente fatto, ma sembra influenzare il modo in cui passa a un post-back.
danjones_mcr

Stai utilizzando la libreria obsoleta react-router-redux( github.com/reactjs/react-router-redux ), a meno che tu non abbia un vincolo speciale da imporre utilizzando versioni obsolete delle librerie react-reduxe react-router, dovresti prendere in considerazione il passaggio a versioni più recenti, poiché potrebbe risolvere il tuo problema ). O si fa l'aggiornamento, oppure è necessario fornire l'esatta versione di react, react-router-redux, react-reduxe react-router-domil progetto è attualmente in uso in modo abbiamo la possibilità di trovare una soluzione patch.
GonArrivi,

Risposte:


2

Ho ricostruito il tuo caso d'uso codesandbox.ioe la "transizione" funziona bene. Quindi forse dare un'occhiata alla mia implementazione potrebbe aiutarti. Tuttavia, ho sostituito l'importazione della libreria con un'importazione di file, quindi non so se questo è il fattore decisivo del perché non funziona senza ricaricare un'intera pagina.

A proposito, cosa intendi esattamente con "senza soluzione di continuità"? Ci sono elementi che rimangono su ogni pagina e non devono essere ricaricati di nuovo quando si fa clic sul collegamento? È come se lo avessi implementato nella sandbox in cui un'immagine statica rimane in alto su ogni pagina.


Dai un'occhiata alla sandbox .

Questo è il example.jsfile

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

E questo è il my-external-library.jsfile:

import React from "react";

export const Heading = ({ withLinkProps }) => {
  const RouterLink = withLinkProps.routerLink;
  return <RouterLink to={withLinkProps.url}>Superlink</RouterLink>;
};

Ciao, molte grazie per la risposta! Sembra che solo quando si passa tramite node_modules, si verifica il problema.
danjones_mcr
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.