web-dev-qa-db-fra.com

Comment arrêter / # / dans le navigateur avec react-router?

Un moyen d'empêcher /#/ de s'afficher dans la barre d'adresse du navigateur lors de l'utilisation de react-router? C'est avec ReactJS. En d'autres termes, cliquer sur les liens pour accéder à un nouvel itinéraire affiche localhost:3000/#/ ou localhost:3000/#/about. En fonction de l'itinéraire.

99
Giant Elk

Pour les versions 1, 2 et 3 de react-router, la méthode appropriée pour définir l'itinéraire vers un schéma de mappage d'URL consiste à transmettre une implémentation d'historique au paramètre history de <Router>. De la documentation d'histoires :

En résumé, un historique sait comment écouter les modifications apportées à la barre d'adresse du navigateur et analyse l'URL dans un objet d'emplacement que le routeur peut utiliser pour faire correspondre les itinéraires et restituer le bon ensemble de composants.

Versions 2 et 3

Dans react-router 2 et 3, le code de configuration de votre route ressemblera à ceci:

import { browserHistory } from 'react-router'
ReactDOM.render (( 
 <Router history={browserHistory} >
   ...
 </Router> 
), document.body);

Version 1

Dans la version 1.x, vous utiliserez plutôt les éléments suivants:

import createBrowserHistory from 'history/lib/createBrowserHistory'
ReactDOM.render (( 
  <Router history={createBrowserHistory()} >
   ...
  </Router> 
), document.body);

Source: Guide de mise à jour version 2.

Version 4

Pour la prochaine version 4 de react-router, la syntaxe a beaucoup changé et il est nécessaire d'utiliser BrowserRouter comme balise racine du routeur.

import BrowserRouter from 'react-router/BrowserRouter'
ReactDOM.render (( 
  <BrowserRouter>
   ...
 <BrowserRouter> 
), document.body);

Source Docs de React Router Version 4

75
Adam Brown
Router.run(routes, Router.HistoryLocation, function (Handler) {
  React.render(<Handler/>, document.body);
});

Pour la version 0.11 actuelle et ultérieure, vous devez ajouter Router.HistoryLocation à Router.run(). <Routes> sont maintenant obsolètes. Voir le Guide de mise à nivea pour l'implémentation de 0.12.x HistoryLocation.

40
pxwise

Si vous n'avez pas besoin de supporter IE8, vous pouvez utiliser l'historique du navigateur et react-router utilisera window.pushState au lieu de définir le hachage.

Cela dépend de la version de React Router que vous utilisez:

21
Sophie Alpert

Vous pouvez réellement utiliser .htaccess pour accomplir cela. Le navigateur a normalement besoin du délimiteur de chaîne de requête ? ou # pour déterminer le début de la chaîne de requête et la fin des chemins de répertoire. Le résultat final que nous voulons est www.mysite.com/dir Il nous faut donc résoudre le problème avant que le serveur Web ne recherche le répertoire pour lequel nous pensons avoir demandé /dir. Nous plaçons donc un fichier .htaccess à la racine du projet.

    # Setting up Apache options
    AddDefaultCharset utf-8
    Options +FollowSymlinks -MultiViews -Indexes
    RewriteEngine on

    # Setting up Apache options (Godaddy specific)
    #DirectoryIndex index.php
    #RewriteBase /


    # Defining the rewrite rules
    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteCond %{SCRIPT_FILENAME} !-f

    RewriteRule ^.*$ ./index.html

Ensuite, vous obtenez les paramètres de requête avec window.location.pathname

Vous pouvez ensuite éviter d'utiliser des itinéraires réactifs si vous le souhaitez et manipuler simplement l'URL et l'historique du navigateur si vous le souhaitez également. J'espère que ça aide quelqu'un ...

9
Garrett Tacoronte

Installer le paquet d'historique

npm install history --save

Importation suivante de createHistory et de useBasename de l'historique

import { createHistory, useBasename } from 'history';
...
const history = useBasename(createHistory)({
  basename: '/root' 
});

si l'URL de votre application est www.example.com/myApp, alors/root doit être/myApp.

transmettre la variable d'historique au routeur

render((
  <Router history={history}>
    ...
  </Router>
), document.getElementById('example'));

Maintenant, pour toutes vos balises Link, ajoutez un "/" devant tous les chemins.

<Link to="/somewhere">somewhere</Link>

L'inspiration de la solution est venue de exemple de React-Router Ce qui, malheureusement, n'a pas été correctement documenté dans leur API.

5
Mox

Une autre façon de gérer les éléments à afficher après le hachage (donc si vous n'utilisez pas pushState!) Consiste à créer votre CustomLocation et à le charger lors de la création de ReactRouter.

Par exemple, si vous voulez avoir l'URL hashbang (donc avec #!) Pour se conformer aux spécifications de Google pour l'analyse, vous pouvez créer un fichier HashbangLocation.js qui copie principalement le HashLocation d'origine, tel que:

'use strict';

var LocationActions = require('../../node_modules/react-router/lib/actions/LocationActions');
var History = require('../../node_modules/react-router/lib/History');

var _listeners = [];
var _isListening = false;
var _actionType;

function notifyChange(type) {
  if (type === LocationActions.Push) History.length += 1;

  var change = {
    path: HashbangLocation.getCurrentPath(),
    type: type
  };

  _listeners.forEach(function (listener) {
    listener.call(HashbangLocation, change);
  });
}

function slashToHashbang(path) {
  return "!" + path.replace(/^\//, '');
}

function ensureSlash() {

  var path = HashbangLocation.getCurrentPath();
  if (path.charAt(0) === '/') {
    return true;
  }HashbangLocation.replace('/' + path);

  return false;
}

function onHashChange() {
  if (ensureSlash()) {
    // If we don't have an _actionType then all we know is the hash
    // changed. It was probably caused by the user clicking the Back
    // button, but may have also been the Forward button or manual
    // manipulation. So just guess 'pop'.
    var curActionType = _actionType;
    _actionType = null;
    notifyChange(curActionType || LocationActions.POP);
  }
}

/**
 * A Location that uses `window.location.hash`.
 */
var HashbangLocation = {

  addChangeListener: function addChangeListener(listener) {
    _listeners.Push(listener);

    // Do this BEFORE listening for hashchange.
    ensureSlash();

    if (!_isListening) {
      if (window.addEventListener) {
        window.addEventListener('hashchange', onHashChange, false);
      } else {
        window.attachEvent('onhashchange', onHashChange);
      }

      _isListening = true;
    }
  },

  removeChangeListener: function removeChangeListener(listener) {
    _listeners = _listeners.filter(function (l) {
      return l !== listener;
    });

    if (_listeners.length === 0) {
      if (window.removeEventListener) {
        window.removeEventListener('hashchange', onHashChange, false);
      } else {
        window.removeEvent('onhashchange', onHashChange);
      }

      _isListening = false;
    }
  },

  Push: function Push(path) {
    _actionType = LocationActions.Push;
    window.location.hash = slashToHashbang(path);
  },

  replace: function replace(path) {
    _actionType = LocationActions.REPLACE;
    window.location.replace(window.location.pathname + window.location.search + '#' + slashToHashbang(path));
  },

  pop: function pop() {
    _actionType = LocationActions.POP;
    History.back();
  },

  getCurrentPath: function getCurrentPath() {
    return decodeURI(
    // We can't use window.location.hash here because it's not
    // consistent across browsers - Firefox will pre-decode it!
    "/" + (window.location.href.split('#!')[1] || ''));
  },

  toString: function toString() {
    return '<HashbangLocation>';
  }

};

module.exports = HashbangLocation;

Notez la fonction slashToHashbang.

Ensuite, il suffit de faire

ReactRouter.create({location: HashbangLocation})

Et c'est tout :-)

3
Jonathan Banon