Passer le lien de react-router-dom dans une bibliothèque externe

10

Je rend des composants à partir de ma bibliothèque de modèles externe (node_modules). Dans mon application principale, je passe mon Linkinstance de react-router-domdans le composant de mes bibliothèques externes comme suit:

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

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

<Heading withLinkProps={articleWithLinkProps} />

Dans ma bibliothèque, ça rend le Linkcomme:

const RouterLink = withLinkProps.routerLink;

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

Le RouterLinksemble s'afficher correctement et navigue même vers l'URL lorsque vous cliquez dessus.


Mon problème est que le RouterLinksemble s'être détaché de l' react-router-dominstance de mon application . Lorsque je clique Heading, la navigation est "difficile", affichant la page au lieu de l'acheminer de façon transparente comme d' Linkhabitude.

Je ne sais pas quoi essayer à ce stade pour lui permettre de naviguer de manière transparente. Toute aide ou conseil serait apprécié, merci d'avance.

Modifier: montrant comment mon routeur est configuré.

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
la source
Pourquoi ne pas avoir votre <Link>composant transmis à votre bibliothèque externe comme argument ou accessoire? cela permettrait plus de flexibilité et sa façon propre de gérer la navigation.
ROOT
Pouvez-vous montrer comment configurer votre routeur? S'agit-il d'un navigateur, d'une mémoire ou d'un routeur statique?
zero298
@ zero298 - Question mise à jour
danjones_mcr
@mamounothman - C'est ainsi que cela se fait actuellement, mais semble affecter la façon dont il navigue vers un post-back.
danjones_mcr
Vous utilisez la bibliothèque obsolète react-router-redux( github.com/reactjs/react-router-redux ), sauf si vous avez une contrainte spéciale à appliquer en utilisant des versions obsolètes des bibliothèques react-reduxet react-router, vous devriez envisager de passer à des versions plus récentes, car cela peut résoudre votre problème ). Soit vous faites la mise à niveau, ou vous devez fournir les versions exactes de react, react-router-redux, react-reduxet react-router-domvotre projet utilise actuellement si nous avons une chance de trouver une solution de ragréage.
GonArrivi

Réponses:

2

J'ai reconstruit votre cas d'utilisation codesandbox.ioet la "transition" fonctionne bien. Alors peut-être que vérifier mon implémentation pourrait vous aider. Cependant, j'ai remplacé l'importation de bibliothèque par une importation de fichier, donc je ne sais pas si c'est le facteur décisif pour expliquer pourquoi cela ne fonctionne pas sans un rechargement de page entière.

Soit dit en passant, que voulez-vous dire exactement par «de façon transparente»? Y a-t-il des éléments qui restent sur chaque page et ne devraient pas être rechargés à nouveau en cliquant sur le lien? C'est comme si je l'avais implémenté dans le bac à sable où une image statique reste en haut de chaque page.


Découvrez le bac à sable .

C'est le example.jsdossier

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

Et voici le my-external-library.jsdossier:

import React from "react";

export const Heading = ({ withLinkProps }) => {
  const RouterLink = withLinkProps.routerLink;
  return <RouterLink to={withLinkProps.url}>Superlink</RouterLink>;
};
New3D
la source
Salut, merci beaucoup pour la réponse! Il semble que ce n'est que lors du passage via node_modules que le problème se produit.
danjones_mcr