Ruthlessly simple bindings to keep react-router and redux in sync

Overview

Project Deprecated

This project is no longer maintained. For your Redux <-> Router syncing needs with React Router 4+, please see one of these libraries instead:


⚠️ This repo is for react-router-redux 4.x, which is only compatible with react-router 2.x and 3.x

react-router-redux

npm version npm downloads build status

Keep your router in sync with application state

Formerly known as redux-simple-router

You're a smart person. You use Redux to manage your application state. You use React Router to do routing. All is good.

But the two libraries don't coordinate. You want to do time travel with your application state, but React Router doesn't navigate between pages when you replay actions. It controls an important part of application state: the URL.

This library helps you keep that bit of state in sync with your Redux store. We keep a copy of the current location hidden in state. When you rewind your application state with a tool like Redux DevTools, that state change is propagated to React Router so it can adjust the component tree accordingly. You can jump around in state, rewinding, replaying, and resetting as much as you'd like, and this library will ensure the two stay in sync at all times.

This library is not necessary for using Redux together with React Router. You can use the two together just fine without any additional libraries. It is useful if you care about recording, persisting, and replaying user actions, using time travel. If you don't care about these features, just use Redux and React Router directly.

Installation

npm install --save react-router-redux

How It Works

This library allows you to use React Router's APIs as they are documented. And, you can use redux like you normally would, with a single app state. The library simply enhances a history instance to allow it to synchronize any changes it receives into application state.

history + store (redux) → react-router-redux → enhanced historyreact-router

Tutorial

Let's take a look at a simple example.

import React from 'react'
import ReactDOM from 'react-dom'
import { createStore, combineReducers } from 'redux'
import { Provider } from 'react-redux'
import { Router, Route, browserHistory } from 'react-router'
import { syncHistoryWithStore, routerReducer } from 'react-router-redux'

import reducers from '<project-path>/reducers'

// Add the reducer to your store on the `routing` key
const store = createStore(
  combineReducers({
    ...reducers,
    routing: routerReducer
  })
)

// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(browserHistory, store)

ReactDOM.render(
  <Provider store={store}>
    { /* Tell the Router to use our enhanced history */ }
    <Router history={history}>
      <Route path="/" component={App}>
        <Route path="foo" component={Foo}/>
        <Route path="bar" component={Bar}/>
      </Route>
    </Router>
  </Provider>,
  document.getElementById('mount')
)

Now any time you navigate, which can come from pressing browser buttons or navigating in your application code, the enhanced history will first pass the new location through the Redux store and then on to React Router to update the component tree. If you time travel, it will also pass the new state to React Router to update the component tree again.

How do I watch for navigation events, such as for analytics?

Simply listen to the enhanced history via history.listen. This takes in a function that will receive a location any time the store updates. This includes any time travel activity performed on the store.

const history = syncHistoryWithStore(browserHistory, store)

history.listen(location => analyticsService.track(location.pathname))

For other kinds of events in your system, you can use middleware on your Redux store like normal to watch any action that is dispatched to the store.

What if I use Immutable.js or another state wrapper with my Redux store?

When using a wrapper for your store's state, such as Immutable.js, you will need to change two things from the standard setup:

  1. By default, the library expects to find the history state at state.routing. If your wrapper prevents accessing properties directly, or you want to put the routing state elsewhere, pass a selector function to access the historystate via the selectLocationState option on syncHistoryWithStore.
  2. Provide your own reducer function that will receive actions of type LOCATION_CHANGE and return the payload merged into the locationBeforeTransitions property of the routing state. For example, state.set("routing", {locationBeforeTransitions: action.payload}).

These two hooks will allow you to store the state that this library uses in whatever format or wrapper you would like.

How do I access router state in a container component?

React Router provides route information via a route component's props. This makes it easy to access them from a container component. When using react-redux to connect() your components to state, you can access the router's props from the 2nd argument of mapStateToProps:

function mapStateToProps(state, ownProps) {
  return {
    id: ownProps.params.id,
    filter: ownProps.location.query.filter
  };
}

You should not read the location state directly from the Redux store. This is because React Router operates asynchronously (to handle things such as dynamically-loaded components) and your component tree may not yet be updated in sync with your Redux state. You should rely on the props passed by React Router, as they are only updated after it has processed all asynchronous code.

What if I want to issue navigation events via Redux actions?

React Router provides singleton versions of history (browserHistory and hashHistory) that you can import and use from anywhere in your application. However, if you prefer Redux style actions, the library also provides a set of action creators and a middleware to capture them and redirect them to your history instance.

import { createStore, combineReducers, applyMiddleware } from 'redux';
import { routerMiddleware, push } from 'react-router-redux'

// Apply the middleware to the store
const middleware = routerMiddleware(browserHistory)
const store = createStore(
  reducers,
  applyMiddleware(middleware)
)

// Dispatch from anywhere like normal.
store.dispatch(push('/foo'))

Examples

Examples from the community:

Have an example to add? Send us a PR!

API

routerReducer()

You must add this reducer to your store for syncing to work.

A reducer function that stores location updates from history. If you use combineReducers, it should be nested under the routing key.

history = syncHistoryWithStore(history, store, [options])

Creates an enhanced history from the provided history. This history changes history.listen to pass all location updates through the provided store first. This ensures if the store is updated either from a navigation event or from a time travel action, such as a replay, the listeners of the enhanced history will stay in sync.

You must provide the enhanced history to your <Router> component. This ensures your routes stay in sync with your location and your store at the same time.

The options object takes in the following optional keys:

  • selectLocationState - (default state => state.routing) A selector function to obtain the history state from your store. Useful when not using the provided routerReducer to store history state. Allows you to use wrappers, such as Immutable.js.
  • adjustUrlOnReplay - (default true) When false, the URL will not be kept in sync during time travel. This is useful when using persistState from Redux DevTools and not wanting to maintain the URL state when restoring state.

push(location), replace(location), go(number), goBack(), goForward()

You must install routerMiddleware for these action creators to work.

Action creators that correspond with the history methods of the same name. For reference they are defined as follows:

  • push - Pushes a new location to history, becoming the current location.
  • replace - Replaces the current location in history.
  • go - Moves backwards or forwards a relative number of locations in history.
  • goForward - Moves forward one location. Equivalent to go(1)
  • goBack - Moves backwards one location. Equivalent to go(-1)

Both push and replace take in a location descriptor, which can be an object describing the URL or a plain string URL.

These action creators are also available in one single object as routerActions, which can be used as a convenience when using Redux's bindActionCreators().

routerMiddleware(history)

A middleware you can apply to your Redux store to capture dispatched actions created by the action creators. It will redirect those actions to the provided history instance.

LOCATION_CHANGE

An action type that you can listen for in your reducers to be notified of route updates. Fires after any changes to history.

Comments
  • Use middleware to synchronize store to history

    Use middleware to synchronize store to history

    Per https://github.com/rackt/redux-simple-router/pull/129#issuecomment-167392040.

    Fixes https://github.com/rackt/redux-simple-router/issues/108.

    The idea is basically - keep unidirectional data flow for updates, most of the time. This works in most cases, but it breaks replay, since the actions in some sense aren't pure. That's fine, though - we can restrict the store observer to only handle the replay case (and potentially not even use it otherwise).

    opened by taion 75
  • 5.0 (React Router 4.0 integration)

    5.0 (React Router 4.0 integration)

    Best viewed here: https://github.com/timdorr/react-router-redux/tree/5.0.x

    This revamps the library for React Router 4.0 integration.

    This is one potential option for how we might integrate things. If not, we can definitely use this scaffolding as a base for something else.

    Currently, this does one-way synchronization of the location from a <*History> (from react-history) to a Redux store. I could have done a more generic <ControlledRouter> that exposes an onChange prop, but this library has a specific purpose and I wanted to avoid excess boilerplate. The only complication is needing to add in an additional reducer. Not really a way to avoid that, but everyone should be used to that from the previous versions.

    Next up is being able to dispatch history actions into the store to issue navigation events.

    Anyways, this is just a beginning and it's in a very mercurial state, so suggestions are definitely welcome.

    opened by timdorr 64
  • Getting `You cannot change <Router routes>; it will be ignored` when hot-loading

    Getting `You cannot change ; it will be ignored` when hot-loading

    When hot-loading I am getting the warning:

    You cannot change <Router routes>; it will be ignored
    

    My process is I save a file in view with some update like I added a <span>, and it shows up on the page, but then this error shows. I checked into it, finding the commit here: https://github.com/rackt/react-router/commit/62f6ef24136b2b80472931e785a75c358e993e90

    I don't know what this does. It looks like it's saying if you're on the current page and the route doesn't change, but everything else stayed the same, then warn.

    opened by Sawtaytoes 62
  • Alternative Proposed Solution For React-Router + Redux Integration

    Alternative Proposed Solution For React-Router + Redux Integration

    (tl;dr - maybe we should use the RouterContext from React-Router v2 for syncing the redux-store? We could get routing-connected components without infinite loops and router props in the store!)

    For starters, I've been really impressed with goals and results that this project has displayed in such a short time. Moving from syncing the pathname to the entire location descriptor as well as improving the support for the devtools while keeping the API super simple and close to React-Router has been a big win for both the users and the maintainers (or at least it appears to be from my end).

    Tying to history directly as the source for updating the store and vice-versa makes this project very flexible (you don't even need React-Router technically), but I think results in some negative consequences:

    1. Connecting to the Routing State is Dangerous

      With syncing with history, you must discourage users from doing what seems natural in a redux setting and connecting the router state to their components (#212) leading to the following in the README:

      Warning: It is a bad pattern to use react-redux's connect decorator to map the state from this reducer to props on your Route components. This can lead to infinite loops and performance problems. react-router already provides this for you via this.props.location.

      I think this is due to the fact that the router props and the redux-store are not from the same source (only indirectly via history) and therefore are not guaranteed to update in sync.

    2. Store omits the React-Router Props

      The second limitation of the history-redux approach is missing out on React-Router's params in the redux -store, the source of confusion and many feature requests (#246, #228, etc)

    I know that you can use the props directly from React-Router, and I've responded to several issues and discord questions with that very advice. I would be happy with these tradeoffs for simplicity if there were not another solution.

    An Alternative using RouterContext

    I think that React-Router 2.x actually provides a best of both worlds approach where we can get an easy API which matches React-Router, maintains a small codebase, and solves the two limitations above. I actually stumbled across this while trying to see if there was a way to upgrade the old redux-router (before this project became part of rackt and added the location object sync).

    Here's an alternative using the RouterContext from React-Router 2. The central idea is that the props passed to the RouterContext are directly from the store, therefore a component below this ReduxRouter cannot ever get a property from the router that is different than the store's data. The ReduxRouterContext is responsible for managing and resolving differences between the store and the props passed down from ReactRouter

    function routerPropsFromProps(props) {
      return {
        location: props.location,
        params: props.params,
      };
    }
    
    @connect(
      (state, { routerStateSelector }) => { return { routerState: routerStateSelector(state) }; },
      { routerDidChange }
    )
    class ReduxRouterContext extends Component {
    
      static propTypes = {
        router: PropTypes.object,
        routerDidChange: PropTypes.func.isRequired,
        routerState: PropTypes.object,
      }
    
      componentWillMount() {
        // On mount, sync to the store to React-Router props
        this.props.routerDidChange(routerPropsFromProps(this.props));
      }
    
      componentWillReceiveProps(newProps) {
        // New routing props from React-Router and it doesnt match our store, Update the store
        if (!routerStateEquals(routerPropsFromProps(newProps), routerPropsFromProps(this.props)) &&
            !routerStateEquals(routerPropsFromProps(newProps), newProps.routerState)) {
          this.props.routerDidChange(routerPropsFromProps(newProps));
        // New store state and it doesnt match the next routing props, transition via the router
        // This is common when replaying devTools
        } else if (!routerStateEquals(newProps.routerState, this.props.routerState) &&
                   !routerStateEquals(routerPropsFromProps(newProps), newProps.routerState)) {
          if (newProps.routerState) {
            newProps.router.transitionTo(newProps.routerState.location);
          }
        }
      }
    
      render() {
        const { routerDidChange, routerState, ...others } = this.props;
        const newRouterProps = {
          ...others,
          ...routerState, // Override react-router's props with the store routing props
        };
        return <RouterContext {...newRouterProps} />;
      }
    }
    
    class ReduxRouter extends Component {
    
      render() {
        return (<Router render={props => <ReduxRouterContext {...props} />}
                       {...this.props}
               />);
      }
    }
    

    I omitted a small wrapper class which facilitates in memoization and passing down the state selector, as well as the routerStateEquals which would compare location objects (maybe omit the key if users dont want a re-render on same page loads #222?). You would also add a small middleware for history so users can do the routeActions.push and other history navigation from redux which would just call history directly. Also of course would be a reducer to store the data from routerDidChange.

    The use for this would be a (really) minor tweak to how users interact with the current React-Router API.

    Basically anywhere a user would use <Router> they use <ReduxRouter> (or ReactRouterRedux :smile: ) or if server rendering, use <ReduxRouterContext> instead of <RouterContext>.

    Feel free to peruse the actual source at https://github.com/mjrussell/redux-router/tree/rr-v2 with tests and the examples (basic and server rendering) originally from redux-router updated.

    The Way Forward

    I'd love for this (way too long) post to be a discussion about the tradeoffs of an approach like this compared to the current implementation/direction. Maybe this implementation is completely flawed and should be thrown out, or there is a similar approach but with some tweaks. Or, this is what Redux-Router should evolve into and then maintain a 2 redux-routing approach in the ecosystem.

    Thanks and keep up all the great work!

    opened by mjrussell 54
  • Split history syncing from action creators

    Split history syncing from action creators

    Big thanks to @gaearon for opening up this can of worms and writing a bunch of code to fix it!

    Here's the history (pun intended) of what led to this: https://github.com/rackt/react-router-redux/issues/252#issuecomment-178980683 -> #255 -> #257 -> rackt/redux#1362 (PR)

    A big giant chunk of this code is copypasta from Dan's work on that Redux PR. I just mashed some buttons until it looked right.

    Changes

    The provided action creators and middleware are now separate from the history<->state syncing function. For the vast majority of cases, using action creators to trigger navigation is obsoleted by React Router's new history singletons provided in 2.0. Building this functionality in by default and coupling it to our history syncing logic no longer makes sense.

    We now sync by enhancing the history instance to listen for navigation events and dispatch those into the store. The enhanced history has its listen method overridden to respond to store changes, rather than directly to navigation events. When this history is provided to <Router>, the router will listen to it and receive these store changes. This means if we time travel with the store, the router will receive those store changes and update based on the location in the store, instead of what the browser says. Normal navigation events (hitting your browser back/forward buttons, telling a history singleton to push a location) flow through the history's listener like normal, so all the usual stuff works A-OK.

    TODOs

    • [x] Add tests
    • [x] Update the documentation
    • [x] Find bugs/edge cases and fix them as best we can.
    • [x] Fix server side rendering

    Fixes #193 Fixes #252

    discussion feature 
    opened by timdorr 51
  • Support query params?

    Support query params?

    This morning I've been playing around with how we could support query params in redux-simple-router (just as a thought experiment).

    In history.listen we receive a Location. With pushPath and replacePath we can change the API to accept LocationDescriptors. However, with no way of creating a LocationDescriptor object from a LocationDescriptor string, it's difficult to support query params.

    Here's an example of the problem:

    pushPath('/foo?a=b')
    // store:
    { location: '/foo?a=b' }
    
    
    pushPath({ pathname: '/foo', query: { a: 'b' } })
    // store:
    { location: { pathname: '/foo', query: { a: 'b' } } }
    
    
    history.push('/foo?a=b')
    // store:
    { location: { pathname: '/foo', query: { a: 'b' } } }
    
    
    <Link to='/foo?a=b'>
    // store:
    { location: { pathname: '/foo', query: { a: 'b' } } }
    

    The problem is of course that every time you pushPath you will get the exact LocationDescriptor you pass in into the store, but every time you history.push or <Link> you'll get an object. We then can't reliably support query params. (If you're very strict about always passing in a LocationDescriptorObject you would have query support, but that feels very fragile.)

    We can of course use history.createLocation right now, but it's most likely no longer going to be public in history V2.

    To support query params we need to be able to create a LocationDescriptor object both from a LocationDescriptor string and from a Location. We could then easily support query params, and we could also deepEqual check them without knowing about query or anything else that's actually part of the LocationDescriptor (which is how we stop cycles, #50). With a createLocationDescriptor (that always returns a LocationDescriptorObject) our code base would actually be simpler, and we would get query support for free.

    Okey, so some potential solutions:

    Keep the solution we have now

    I.e. path and state in store, but change to accepting LocationDescriptor in push and replace. We don't support query params.

    Verbatim LocationDescriptor in store

    We have to make it very clear that this is either an object or a string. So it's most likely not very usable for people. We "support" query params, iff you're very strict about always passing in a LocationDescriptorObject. Fragile.

    Always go through history "before" store

    pushPath
    -> UPDATE_PATH_INTERNAL action
    -> store.subscribe callback
    -> history.push
    -> history.listen callback
    -> UPDATE_PATH action
    -> store.subscribe callback where we break cycle
    

    I.e. we don't trigger UPDATE_PATH immediately, but only within the history.listen callback. We would then reliably have a LocationDescriptorObject in the store, and we could therefore reliably support query params.

    This is of course a more complex solution.

    Conclusion

    It was interesting going through the different solutions, but with createLocation going away and no createLocationDescriptor on the horizon I think it's best to just keep our current solution. I don't think it's worth the added complexity.

    Maybe someone else has ideas on how to solve this? Or maybe this is another case for keeping history.createLocation public? @jlongster @mjackson @taion @justingreenberg

    (Hopefully I haven't overlooked something very obvious :see_no_evil:)

    opened by kimjoar 51
  • Clarifying the goals of this project

    Clarifying the goals of this project

    I think I’m getting a little confused by the goals and the scope of this project. I’d appreciate @jlongster weighing in on this.

    I see a few things it does right now:

    • (1) Provides state.routing for other middleware, components, and action creators to read. I believe this is problematic: it doesn’t match the rendered route because of the potential for async transitions in between. This is the reason we warn people not to use state.routing in mapStateToProps() which I believe is confusing, and even if they don’t use it in components, they still might use it in action creators and expect it to correspond to the router’s current state. So I’m not sure whether this is a good feature to keep.
    • (2) Provides an actions-first interface to side effects of history. While this may be convenient, I think the reason people want this is not because actions are the best interface for causing routing changes, but rather because people don’t want to deal with context or pass history around. Many people are also feeling pressured to express everything with Redux primitives (actions) even if the problem at hand is not expressed with them well. Consider that history.pushState() is not much different from fetch() (it’s a side effect) but nobody expects us to provide “fetch action creators”. The real problem here seems to be the perceived difficulty of passing history around or importing it, rather than the need for history updates to be actions.
    • (3) Allows replaying the history changes from DevTools or another action replay mechanism. This is where it gets interesting. It seems to me that the ability to persist routing state together with everything else and re-render the app based on current state rather than what the browser thinks was the original point of this library. This feature seems to explain the need for action creators: you want navigations to be in the log so they can potentially be replayed. However such functionality would only be useful in dev (or otherwise special) environment.

    As we evolve (or not evolve) this library, I want to better understand which of these points are actually important to the author, and which are just a byproduct of current user habits and their desire to express everything “the Redux way”.

    Essentially, I want to understand what value react-router-redux brings over react-router + history in production mode other than the familiar mental model (“just dispatch actions”), the ability to reach out into state.routing (which can be dangerous and may not reflect the UI but can be convenient for apps without async transitions), and not having to think about how to access history without passing it around.

    In no way am I trying to diminish the work being done here. I just want to figure out for myself whether presistence/time-travely part of this library could be a separate dev-only project, and whether what would be left is not essentially a feature request for better documentation and less ceremony when accessing history from action creators and other middleware.

    Thank you!

    question 
    opened by gaearon 49
  • Implement in react-redux-universal-hot-example

    Implement in react-redux-universal-hot-example

    There's some talk about this library in https://github.com/erikras/react-redux-universal-hot-example/issues/439

    Would you be interested in starting a branch to integrate this library as a replacement? It could serve as a good example on how to migrate from redux-router to redux-simple-router, and could uncover pain points along the way.

    I'd be happy to help, too. But for the next few days, probably not much.

    If you think it would not serve as a good replacement, that would be great information, too!

    opened by quicksnap 44
  • react-route's onEnter handler called twice

    react-route's onEnter handler called twice

    I've found, that applying current react-router-redux (4.0.7) causes twice calling react-router's asynchronous (with 3 arguments) onEnter handler while initial loading. Here is a gist, describing this issue https://gist.github.com/semurgx/9abb0d02ea49f49aa97ef34cac117f5f .

    opened by semurgx 38
  • Rename to react-router-redux

    Rename to react-router-redux

    @ryanflorence and @mjackson have invited this project to join the rackt set of projects since it aligns well with how they envision react-router and redux integration. I think it will essentially replace redux-router and that will live as its own standalone project.

    We're considering renaming it react-router-redux as it will be more official bindings. Unless anyone has any better ideas, I say we go with it.

    opened by jlongster 35
  • Support ImmutableJS Map as the state

    Support ImmutableJS Map as the state

    Although it makes sense to use ImmutableJS Map object as your state object - it currently can't be done because the reducer of redux-simple-router uses simple Object.assign. Please consider supporting it by allowing to pass a custom reducer, or a reducer's internal state creator, such as (state, obj) => newState.

    opened by zavelevsky 33
  • syncHistoryWithStore does not respect redux state

    syncHistoryWithStore does not respect redux state

    Hi,

    I am trying to restore the displayed page on app startup but it's always /, redux store is preloaded from local storage. HoweversyncHistoryWithStore erases the state.

    I use redux-localstorage to persist redux to local storage which seems to be merging state from local storage into initialState therefore restoring the state without telling anyone which shouldn't be any different for the app when the concept of single source of truth is applied.

    I am sure this issue can be reproduced with initialState with hardcoded route.

    import { routerMiddleware, routerReducer as routing } from 'react-router-redux';
    import persistState from 'redux-localstorage';
    import thunk from 'redux-thunk';
    import routes from './routes';
    
    const router = routerMiddleware(hashHistory);
    
    const reducers = {
      routing
    };
    
    const middlewares = [ thunk, router ];
    
    function configureStore(initialState) {
      const enhancer = compose(applyMiddleware(...middlewares), persistState());
      const rootReducer = combineReducers(reducers);
      
      return createStore(rootReducer, initialState, enhancer);
    }
    
    const initialState = {};
    const store = configureStore(initialState);
    const routerHistory = syncHistoryWithStore(hashHistory, store);
    
    ReactDOM.render(
      <Provider store={ store }>
        <Router history={ routerHistory } routes={ routes } />
      </Provider>,
      rootElement
    );
    

    I tried adjustUrlOnReplay without luck:

    const routerHistory = syncHistoryWithStore(hashHistory, store, { adjustUrlOnReplay: true });
    

    Thanks

    opened by pronebird 6
Releases(v4.0.7)
  • v4.0.7(Nov 3, 2016)

  • v4.0.6(Sep 22, 2016)

  • v4.0.5(Jun 6, 2016)

  • v4.0.4(Apr 25, 2016)

  • v4.0.2(Apr 8, 2016)

  • v4.0.1(Apr 8, 2016)

  • v4.0.0(Feb 23, 2016)

    This is a big breaking release, but the last one for the foreseeable future. The scope of this library has changed, so please re-evaluate its usefulness to you. You may not need it and this is ok!

    Summary of Changes

    The provided action creators and middleware are now separate from the history<->state syncing function. For the vast majority of cases, using action creators to trigger navigation is obsoleted by React Router's new history singletons provided in 2.0. Building this functionality in by default and coupling it to our history syncing logic no longer makes sense.

    We now sync by enhancing the history instance to listen for navigation events and dispatch those into the store. The enhanced history has its listen method overridden to respond to store changes, rather than directly to navigation events. When this history is provided to <Router>, the router will listen to it and receive these store changes. This means if we time travel with the store, the router will receive those store changes and update based on the location in the store, instead of what the browser says. Normal navigation events (hitting your browser back/forward buttons, telling a history singleton to push a location) flow through the history's listener like normal, so all the usual stuff works A-OK.

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-rc.2(Feb 19, 2016)

  • v4.0.0-rc.1(Feb 17, 2016)

    This is a promotion of the previous release to release candidate status. Docs have been updated and there's a new server-side rendering example available. Please test this out!

    Source code(tar.gz)
    Source code(zip)
  • v4.0.0-beta.1(Feb 8, 2016)

    Sorry for the API churn, but we have another big release coming soon. Most of the magic is happening in #259.

    Browse the source/docs for this release

    Core Changes

    The provided action creators and middleware are now separate from the history<->state syncing function. For the vast majority of cases, using action creators to trigger navigation is obsoleted by React Router's new history singletons provided in 2.0. Building this functionality in by default and coupling it to our history syncing logic no longer makes sense.

    We now sync by enhancing the history instance to listen for navigation events and dispatch those into the store. The enhanced history has its listen method overridden to respond to store changes, rather than directly to navigation events. When this history is provided to <Router>, the router will listen to it and receive these store changes. This means if we time travel with the store, the router will receive those store changes and update based on the location in the store, instead of what the browser says. Normal navigation events (hitting your browser back/forward buttons, telling a history singleton to push a location) flow through the history's listener like normal, so all the usual stuff works A-OK.

    Source code(tar.gz)
    Source code(zip)
  • 3.0.0(Feb 3, 2016)

    Technically, 2.1.0 broke semver. The appropriate @timdorr's have been flogged. So, we're bumping the major version to catch up.

    Changes

    • Fixed Resets in Redux Dev Tools. 3ae8110f
    • Ensure the initialState is set properly. a00acfd4
    • Support any number of args on action creators 524898b5
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Jan 24, 2016)

    Renamed to react-router-redux. Update your package.jsones appropriately!

    • listenForReplays has a selectLocationState selector. #218
    • Provide unscoped action creators. #225
    • Example updated to use fully ES2015 syntax.
    Source code(tar.gz)
    Source code(zip)
  • 2.0.4(Jan 24, 2016)

  • 2.0.3(Jan 24, 2016)

  • 2.0.2(Jan 24, 2016)

    Versions 2.0.0 and 2.0.1 were test releases for the 2.0 series. 2.0.2 is the first public release.

    A whole new API, with many breaking changes:

    • syncReduxAndRouter is gone. Instead, call syncHistory with just the history object, which returns a middleware that you need to apply. (#141)
    • If you use redux devtools, you need to call middleware.listenForReplays(store) on the middleware returned from syncHistory. Create the store first with the middleware, then call this function with the store.
    • Action creators are now contained in a single object called routeActions. go, goBack, and goForward action creators have been added.
    • UPDATE_PATH is now UPDATE_LOCATION.
    • The fully parsed location object is now stored in the state instead of a URL string. To access the path, use state.routing.location.pathname instead of state.routing.path.

    View the new docs

    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Jan 24, 2016)

  • 1.0.1(Jan 24, 2016)

    • Solve problem with basename causing infinite redirects (#103)
    • Switched to ES6 imports/exports internally, but should not affect outside users
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0(Jan 24, 2016)

    Breaking Changes:

    • The updatePath action creator has been removed in favor of pushPath and replacePath. Use pushPath to get the same behavior as before. (#38)
    • We have added support for routing state (#38)
    • Our actions are now FSA compliant. This means if you are listening for the UPDATE_PATH action in a reducer you should get properties off the payload property. (#63)

    Other fixes:

    • Redux DevTools should now work as expected (#73)
    • As we no longer depend on window.location, <base href="..."> should now work (#62)
    • We've done lots of work on finding the right way to stop cycles, so hopefully we shouldn't have any unnecessary location or store updates (#50)
    Source code(tar.gz)
    Source code(zip)
Owner
React Community
React website and its localizations
React Community
Official React bindings for Redux

React Redux Official React bindings for Redux. Performant and flexible. Installation Using Create React App The recommended way to start new apps with

Redux 22.5k Jan 1, 2023
Redux bindings for client-side search

redux-search Higher-order Redux library for searching collections of objects. Search algorithms powered by js-worker-search. Check out the live demo a

Brian Vaughn 1.4k Jan 2, 2023
Redux Tutorial - share my experience regarding redux, react-redux and redux-toolkit

Redux Tutorial 1. Introduction to Redux 1.1 What is Redux & why Redux? A small JS Library for managing medium/large amount of states globally in your

Anisul Islam 36 Dec 29, 2022
Skeleton React App configured with Redux store along with redux-thunk, redux persist and form validation using formik and yup

Getting Started with React-Redux App Some Configrations Needed You guys need to modify the baseUrl (path to your server) in the server.js file that is

Usama Sarfraz 11 Jul 10, 2022
A simple app for study react with redux, redux saga and typescript.

React com Redux, Redux-Saga e TypeScript. ?? Uma aplicação simple para entender o funcionamento do Redux e a melhor maneira de utiliza-lo junto com o

João Marcos Belanga 1 May 24, 2022
A lightweight state management library for react inspired by redux and react-redux

A lightweight state management library for react inspired by redux and react-redux

null 2 Sep 9, 2022
Redux - Create forms using Redux And React

Exercício de fixação Vamos criar formulários utilizando Redux! \o/ Antes de inic

Márcio Júnior 2 Jul 21, 2022
redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.js state.

redux-immutable redux-immutable is used to create an equivalent function of Redux combineReducers that works with Immutable.js state. When Redux creat

Gajus Kuizinas 1.9k Dec 30, 2022
A chart monitor for Redux DevTools https://www.npmjs.com/package/redux-devtools-chart-monitor

Redux DevTools Chart Monitor This package was merged into redux-devtools monorepo. Please refer to that repository for the latest updates, issues and

Redux 293 Nov 13, 2022
A simple, lightweight library for managing navigation history in React and Redux

?? Beta version ⚛ Redux history made easy! A simple, lightweight library for managing navigation history in React and Redux. Used in production by Uti

Isis☕Caffe 6 Dec 22, 2022
An i18n solution for React/Redux and React Native projects

redux-react-i18n An i18n solution with plural forms support for Redux/React Workers of all countries, unite! Supported languages list with expected co

Dmitry Erzunov 64 Oct 19, 2022
Front-end of the movie application created with React.js and Redux

# Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run:

Bibi 6 Aug 21, 2021
This command line helps you create components, pages and even redux implementation for your react project

react-help-create This command line helps you create components, pages and even redux implementation for your react project. How to install it? To ins

Omar 27 Dec 10, 2022
Single page application for tracking cryptocurrencies. Includes sorting, animations, graphs and more. Made using React & Redux.

Crypto Tracker A single page application meant to keep track of the most popular crypto currencies status. The user can sort the coins by highest gain

Robert Baiesita 17 Dec 18, 2022
React with Redux, action, dispatch, reducer, store setup and guide

This Project has Snippets for react with redux steup, process and how to implemenntation details src->components->HomeButtons has old approach src->co

Mohib Khan 1 Nov 22, 2021
Shop Cart Page Built Using React And Redux

Getting Started with react-redux-jest-shop Shop cart page with use: React,redux,redux-thunk, API,JEST, LTR Steps for run git clone or download react-r

Renat Khakimoff 1 Apr 24, 2022
Single Page Application that uses Rick and Morty API along with React & Redux

Rick and Morty Rick and Morty Characters Web Page. Single Page Application that

Orçun Uğur 6 Apr 16, 2022
A little e-commerce website made with React.js, Redux and Bootstrap.

E-commerce React JS (in progress) This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: npm st

Gabriela Costa 2 Jan 2, 2022
A React-Redux based project, built with pair programming and gitflow, following this kanban workflow

This is a React-Redux based project, built with pair programming and gitflow, following this kanban workflow. The page have a global state that holds the Rockets and missions from the spaceX API, and allow you to reserve them, displaying on your profile section the missions that you own.

Andrés Felipe Arroyave Naranjo 10 Apr 5, 2022