redux-first-history vs connected-react-router vs react-router vs react-router-redux vs redux-logger
React ルーティングと状態管理ライブラリ
redux-first-historyconnected-react-routerreact-routerreact-router-reduxredux-logger類似パッケージ:

React ルーティングと状態管理ライブラリ

これらのライブラリは、React アプリケーションにおけるルーティングと状態管理を簡素化するために設計されています。ルーティングは、ユーザーがアプリケーション内を移動する際のナビゲーションを管理し、状態管理はアプリケーションの状態を効率的に管理することを目的としています。これにより、開発者はユーザーエクスペリエンスを向上させることができます。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
redux-first-history91,35345399.3 kB152年前MIT
connected-react-router04,699444 kB176-MIT
react-router056,2854.18 MB15312日前MIT
react-router-redux07,768-19年前MIT
redux-logger05,734-589年前MIT

機能比較: redux-first-history vs connected-react-router vs react-router vs react-router-redux vs redux-logger

ルーティングの統合

  • redux-first-history:

    Redux First History は、Redux の設計原則に従ったルーティング管理を提供します。アプリケーションの状態とルーティングを完全に統合し、状態管理の一環としてルーティングを扱うことができます。

  • connected-react-router:

    Connected React Router は、Redux ストアと直接統合されており、ルートの変更をストアに反映させることができます。これにより、アプリケーションの状態とルーティングの一貫性が保たれ、ナビゲーションの履歴を簡単に管理できます。

  • react-router:

    React Router は、シンプルで直感的な API を提供し、コンポーネントベースのルーティングをサポートします。動的なルーティングやネストされたルートを簡単に設定でき、柔軟なナビゲーションを実現します。

  • react-router-redux:

    React Router Redux は、React Router のルーティング状態を Redux ストアに統合します。これにより、アプリケーションの状態を一元管理し、ルーティングの変更を Redux アクションとして扱うことができます。

  • redux-logger:

    Redux Logger は、Redux ストアの状態変化をリアルタイムで監視し、コンソールにログを出力します。これにより、状態管理のデバッグが容易になり、アプリケーションの動作を理解しやすくなります。

デバッグ機能

  • redux-first-history:

    Redux First History は、Redux の状態管理と統合されているため、ルーティングの状態を簡単にデバッグできます。

  • connected-react-router:

    Connected React Router には、Redux ストアとの統合により、ルーティングの変更を追跡するためのデバッグ機能が組み込まれています。これにより、アプリケーションのナビゲーションの流れを簡単に追跡できます。

  • react-router:

    React Router 自体にはデバッグ機能はありませんが、シンプルな構造のため、ルーティングの問題を特定しやすいです。

  • react-router-redux:

    React Router Redux は、Redux のデバッグツールと組み合わせることで、ルーティングの状態を視覚化し、問題を特定するのに役立ちます。

  • redux-logger:

    Redux Logger は、Redux ストアの状態変化をリアルタイムで表示し、アプリケーションの動作を追跡するのに非常に便利です。

学習曲線

  • redux-first-history:

    Redux First History は、Redux の知識が必要ですが、ルーティングの管理が一貫しているため、長期的には学習する価値があります。

  • connected-react-router:

    Connected React Router は、Redux に慣れている開発者にとっては比較的簡単に学べますが、Redux の概念を理解していないと難しい場合があります。

  • react-router:

    React Router は、シンプルな API を持つため、学習曲線は緩やかです。基本的な使い方を理解するのは容易ですが、複雑なルーティングを扱う場合は学習が必要です。

  • react-router-redux:

    React Router Redux は、React Router と Redux の両方の知識が必要です。これにより、学習曲線はやや急になりますが、統合された状態管理の利点があります。

  • redux-logger:

    Redux Logger は、特別な学習を必要とせず、Redux の基本を理解していればすぐに使えます。

拡張性

  • redux-first-history:

    Redux First History は、Redux の原則に従って設計されているため、他の Redux ミドルウェアと組み合わせて拡張可能です。

  • connected-react-router:

    Connected React Router は、Redux のミドルウェアとして機能するため、他のミドルウェアと組み合わせて拡張することが可能です。

  • react-router:

    React Router は、プラグインやカスタムルートを作成することで、非常に高い拡張性を持っています。

  • react-router-redux:

    React Router Redux は、Redux の拡張機能を利用できるため、状態管理を強化することができます。

  • redux-logger:

    Redux Logger は、他のミドルウェアと組み合わせて使用することで、状態管理のデバッグをさらに強化できます。

選び方: redux-first-history vs connected-react-router vs react-router vs react-router-redux vs redux-logger

  • redux-first-history:

    Redux First History は、Redux の設計原則に従ってルーティングを管理したい場合に適しています。特に、アプリケーションの状態を Redux に完全に統合したい場合に選択してください。

  • connected-react-router:

    Connected React Router は、Redux ストアと連携してルーティングを管理したい場合に最適です。Redux を使用しているアプリケーションで、ルートの変更をストアに反映させたい場合に選択してください。

  • react-router:

    React Router は、シンプルで軽量なルーティングライブラリを求めている場合に適しています。特に、Redux を使用しないアプリケーションや、基本的なルーティング機能を必要とする場合に選択してください。

  • react-router-redux:

    React Router Redux は、React Router と Redux を統合したい場合に選択します。Redux ストアとルーティングの状態を同期させる必要がある場合に便利です。

  • redux-logger:

    Redux Logger は、Redux ストアの状態変化をデバッグしたい場合に選択します。アプリケーションの状態管理を可視化し、デバッグを容易にするためのツールです。

redux-first-history のREADME

redux-first-history


Redux First History - Make Redux 100% SINGLE-AND-ONLY source of truth!

Redux history binding for

Compatible with immer - redux-immer - redux-immutable.

:tada: A smaller, faster, optionated, issue-free alternative to connected-react-router

Table of Contents

Main Goal

While working with relatively large projects, it's quite common to use both redux and react-router.

So you may have components that take location from the redux store, others that take location from router context, and others from withRouter HOC.

This can generate sync issues, due to the fact that many components are updated at different times. In addition, React shallowCompare rendering optimization will not work as it should.

With redux-first-history, you can mix components that get history from wherever, they will always be tunneled to state.router.location !

Use whatever you like. History will just work as it should.

//react-router v5 - v6
useLocation() === state.router.location

//react-router v5
this.props.history.location === state.router.location
this.props.location === state.router.location
withRouter.props.location === state.router.location

//react-router v4
this.context.router.history.location === state.router.location
this.context.route.location === state.router.location

//@reach/router
this.props.location === state.router.location

//wouter - pathname
useLocation()[0] === state.router.location.pathname

Mix redux, redux-saga, react-router, @reach/router, wouter and react-location without any synchronization issue!
Why? Because there is no synchronization at all! There is only one history: reduxHistory!

  • One way data-flow
  • One unique source of truth
  • No more location issues!

Edit Redux-First Router Demo

Demo

Main Features

  • 100% one source of truth (store)
  • No synchronization depending on rendering lifecycle (ConnectedRouter)
  • No React dependency (we want history to be always in store!)
  • 100% one-way data flow (only dispatch actions!)
  • Improve React shallowCompare as there is only one "location"
  • Support react-location 3.x
  • Support react-router v4 / v5 / v6
  • Support @reach/router 1.x
  • Support wouter 2.x
  • Support mix react-router, @reach/router & wouter in the same app!
  • Fast migration from an existing project, with the same LOCATION_CHANGE and push actions (taken from RRR)
  • Handle Redux Travelling from dev tools (that's nonsense in production, but at the end of the day this decision it's up to you ...)

Installation

Using npm:

$ npm install --save redux-first-history

Or yarn:

$ yarn add redux-first-history

Usage

store.js

import { createStore, combineReducers, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { createReduxHistoryContext, reachify } from "redux-first-history";
import { createWouterHook } from "redux-first-history/wouter";
import { createBrowserHistory } from 'history';

const { createReduxHistory, routerMiddleware, routerReducer } = createReduxHistoryContext({ 
  history: createBrowserHistory(),
  //other options if needed 
});

export const store = createStore(
  combineReducers({
    router: routerReducer
    //... reducers //your reducers!
  }),
  composeWithDevTools(
    applyMiddleware(routerMiddleware)
  )
);

export const history = createReduxHistory(store);
//if you use @reach/router 
export const reachHistory = reachify(history);
//if you use wouter
export const wouterUseLocation = createWouterHook(history);

store.js (with @reduxjs/toolkit)

import { combineReducers } from "redux";
import { configureStore } from "@reduxjs/toolkit";
import { createReduxHistoryContext } from "redux-first-history";
import { createBrowserHistory } from "history";

const {
  createReduxHistory,
  routerMiddleware,
  routerReducer
} = createReduxHistoryContext({ history: createBrowserHistory() });

export const store = configureStore({
  reducer: combineReducers({
    router: routerReducer
  }),
  middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(routerMiddleware),
});

export const history = createReduxHistory(store);

app.js

import React, { Component } from "react";
import { Provider, connect } from "react-redux";
import { Router } from "react-router-dom";
import { store, history } from "./store";

const App = () => (
      <Provider store={store}>
        <Router history={history}>
        //.....
        </Router>
      </Provider>
    );

export default App;

app.js (react-router v6)

import React, { Component } from "react";
import { Provider } from "react-redux";
import { HistoryRouter as Router } from "redux-first-history/rr6";
import { store, history } from "./store";

const App = () => (
      <Provider store={store}>
        <Router history={history}>
        //.....
        </Router>
      </Provider>
    );

export default App;

saga.js (react-saga)

import { put } from "redux-saga/effects";
import { push } from "redux-first-history";

function* randomFunction() {
  //....
  yield put(push(YOUR_ROUTE_PATH));
  //....
}

slice.js (in a Thunk with @reduxjs/toolkit)

import { push } from "redux-first-history";

export const RandomThunk = (dispatch) => {
  //....
  dispatch(push(YOUR_ROUTE_PATH));
  //....
}
  • Just a simple Router with no more ConnectedRouter!
  • Probably, you already did connect the Redux store with react-router-redux or connected-react-router (in this case you have only to replace the import!)

Options

export const createReduxHistoryContext = ({
  history, 
  routerReducerKey = 'router', 
  reduxTravelling = false, 
  selectRouterState = null,
  savePreviousLocations = 0,
  batch = null,
  reachGlobalHistory = null
})
keyoptionaldescription
historynoThe createBrowserHistory object - v4.x/v5.x
routerReducerKeyyesif you don't like router name for reducer.
reduxTravellingyesif you want to play with redux-dev-tools :D.
selectRouterStateyescustom selector for router state. With redux-immutable selectRouterState = state => state.get("router")
savePreviousLocationsyesif > 0 add the key "previousLocation" to state.router, with the last N locations. [{location,action}, ...]
batchyesa batch function for batching states updates with history updates. Prevent top-down updates on react : usage import { unstable_batchedUpdates } from 'react-dom'; batch = unstable_batchedUpdates
reachGlobalHistoryyesglobalHistory object from @reach/router - support imperatively navigate of @reach/router - import { navigate } from '@reach/router' : usage import { globalHistory } from '@reach/router'; reachGlobalHistory = globalHistory
basenamenosupport basename (history v5 fix)

Advanced Config

  • Support "navigate" from @reach/router
import { createReduxHistoryContext, reachify } from "redux-first-history";
import { createBrowserHistory } from 'history';
import { globalHistory } from '@reach/router';

const { createReduxHistory, routerMiddleware, routerReducer } = createReduxHistoryContext({ 
  history: createBrowserHistory(),
  reachGlobalHistory: globalHistory,
  //other options if needed 
});
  • React batch updates: top-down batch updates for maximum performance. Fix also some updated edge cases.
import { createReduxHistoryContext, reachify } from "redux-first-history";
import { createBrowserHistory } from 'history';
import { unstable_batchedUpdates } from 'react-dom';

const { createReduxHistory, routerMiddleware, routerReducer } = createReduxHistoryContext({ 
  history: createBrowserHistory(),
  batch: unstable_batchedUpdates,
  //other options if needed 
});

Feedback

Let me know what do you think!
Enjoy it? Star this project! :D

Credits & Inspiration

  • redux-first-routing
  • react-router-redux
  • connected-react-router

Contributors

See Contributors.

License

MIT License.