ブラウザでreact-routerを使用して/#/を停止する方法は?


103

/#/react-routerを使用しているときにブラウザーのアドレスバーに表示されないようにする方法はありますか?それはReactJSについてです。つまり、リンクをクリックして新しいルートに移動すると、localhost:3000/#/またはが表示され localhost:3000/#/aboutます。ルートによります。


1
これはHashHistoryiso を使用するためBrowserHistoryです。また、このSOに関する質問も参照してください。この問題に関する多くの背景情報を提供します。
Stijn de Witt

回答:


78

react-routerのバージョン1、2、および3の場合、URLマッピングスキームへのルートを設定する正しい方法は、履歴の実装をのhistoryパラメーターに渡すことです<Router>履歴ドキュメントから:

簡単に言うと、履歴はブラウザのアドレスバーの変更をリッスンする方法を知っており、URLを解析して、ルーターがルートを照合し、正しいコンポーネントセットをレンダリングするために使用できるロケーションオブジェクトに変換します。

バージョン2および3

react-router 2および3では、ルート構成コードは次のようになります。

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

バージョン1

バージョン1.xでは、代わりに以下を使用します。

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

出典:バージョン2.0アップグレードガイド

バージョン4

次のバージョン4のreact-routerでは、構文が大幅に変更されてBrowserRouterおり、ルーターのルートタグとして使用する必要があります。

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

Source Reactルーターバージョン4ドキュメント


6
これhistoryは、インストールする必要があるスタンドアロンパッケージです。
Jan Klimo 2015年

4
彼らbrowserHistoryはv2.xでを変更しました。react -routerアップグレードガイドをimport { browserHistory } from 'react-router' <Router history={browserHistory} />チェックしてください
ピストウ

@pistouに感謝します。バージョン2.0への回答を更新しました。
Adam Brown

1
の場合hashHistory、最後にこのクエリパラメータを削除する方法はありますか?http://localhost:8080/#/dashboard?_k=yqwtyu
Con Antonakos 2016年

2
@Matt動作しますが、サーバーでのサポートが必要です。これは、更新すると、パス付きのURLでサーバーにアクセスするためです。
Stijn de Witt

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

現在のバージョン0.11以降では、に追加Router.HistoryLocationする必要がありますRouter.run()<Routes>廃止されました。0.12.x HistoryLocationの実装については、アップグレードガイド参照してください


1
これは私のアプリを完全に台無しにしました。現在の実装にはバグがあるように見えますか?
忍者

2
@Ninjaは、reactおよびreact-routerの正確なバージョン番号を含む新しい質問を投稿し、失敗したコードと受信したエラーをおそらく投稿します。
pxwise 2015

@Chet反応ルーターのドキュメントがシャッフルされたようです。アップグレードガイドにあるHistoryLocationの唯一のリファレンスへのリンクを更新しました。
pxwise

21

IE8をサポートする必要がない場合は、ブラウザーの履歴を使用できますwindow.pushState。ハッシュを設定する代わりに、react-routerが使用します。

これを正確に行う方法は、使用しているReact Routerのバージョンによって異なります。


@ ben-alpertに感謝します。
ジャイアントエルク2014

1
<Routes location="history">途中でブラウザーを更新するまで、つまりlocalhost:3000/about404エラーが発生するまで、すべて正常に機能するように追加しました。それは期待されていpython -m SimpleHTTPServer 3000ますか、私は使っていますか?
ジャイアントエルク2014

5
サーバーサイドがプッシュ状態のURLを処理できることを確認する必要があります。この場合、それはおそらく、アプリが何を提供していても、常に同じルートに到達するすべてのURLを送信するようにする必要があることを意味します。つまり、/about実際にルートページが読み込まれます/。それ以外の場合、サーバーは一致/aboutして何も見つからないルートを探します(404)。私は個人的にpythonを使用していませんが、通常は手動ルート/*または/.*->のいずれかが見つかります。/またはhtml5Mode、サーバー設定でURL と呼ばれるものである可能性があります。
マイクドライバー

3
IE9はpushStateもサポートしていません。つまり、「IE9をサポートする必要がない場合」ということです。私が間違っていたらなあ。
Cymen、2015

1
そのgithubリンクは現在見つからないページです。
k00k 2016年

9

実際に.htaccessを使用してこれを実現できます。ブラウザは通常、クエリ文字列の区切り文字を?必要#とするか、クエリ文字列の始まりとディレクトリパスの終わりを決定する必要があります。最終的な結果は次のとおりですwww.mysite.com/dir 。Webサーバーが要求したと思うディレクトリをWebサーバーが検索する前に、問題をキャッチする必要があります/dir。したがって.htaccess、プロジェクトのルートにファイルを配置します。

    # 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

次にwindow.location.pathnameでクエリパラメータを取得します

その後、必要に応じてリアクションルートの使用を回避し、必要に応じてURLとブラウザの履歴を操作することもできます。これが誰かを助けることを願っています...


Jbossに相当するものは何ですか?
Raghavan

5

履歴パッケージをインストールする

npm install history --save

次に、履歴からcreateHistoryとuseBasenameをインポートします

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

アプリのURLがwww.example.com/myAppの場合、/ rootは/ myAppにする必要があります。

履歴変数をルーターに渡す

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

すべてのリンクタグについて、すべてのパスの前に「/」を追加します。

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

ソリューションのインスピレーションは、 残念ながらAPIに適切に文書化されていないReact-Router Exampleからきています。


これにはノードサーバーが必要ですか?私は同じURLスタイルを達成しようとしていますが、クライアント側でのみです。出来ますか?
Sebastialonso

1
いいえ、ノードサーバーは必要ありません。実際、私はdjangoバックエンドで実行しています。しかし、おそらくツール用のノードが必要です。
Mox

1
わかりました、私はこのアプローチを試しました。F5キーを押すと、「見つかりません」だけが表示されます。この歴史がそれに対処することは可能ですか?
Sebastialonso

uが見つからない場合は、サーバーから返されます。これは、URLパターンが反応ルーターの一部ではないことを意味します。
Mox

1
はい、もう少し読んだ後、すべてが明らかになりました。キーなしでhashHistoryを使用することになりました。
Sebastialonso

3

ハッシュの後に何を表示するかを処理する別の方法(つまり、pushStateを使用しない場合!)は、CustomLocationを作成し、ReactRouterの作成時にロードすることです。

たとえば、クロールに関するGoogleの仕様に準拠するためにハッシュバンのURL(#を使用)が必要な場合は、主に次のような元のHashLocationをコピーするHashbangLocation.jsファイルを作成できます。

'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;

slashToHashbang関数に注意してください。

それからあなたは正義をしなければなりません

ReactRouter.create({location: HashbangLocation})

以上です :-)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.