reactjs / react-router-redux

Ruthlessly simple bindings to keep react-router and redux in sync
https://www.npmjs.com/package/react-router-redux
MIT License
7.81k stars 644 forks source link

syncHistory() does not exist? (can not do example because of it) #155

Closed jasonswearingen closed 8 years ago

jasonswearingen commented 8 years ago

I'm trying to follow along the basic example, but have a problem. The file https://github.com/rackt/redux-simple-router/blob/master/examples/basic/app.js

has a line:

const middleware = syncHistory(history);

where the syncHistory() method is defined in redux-simple-router

but that method does not actually exist, so I can't complete the example.

I tried using the following lines from the readme.md instead

const store = createStore(reducer)
const history = createHistory()
syncReduxAndRouter(history, store)

but doing that and when running I get a exception: cannot read property 'number' of undefined

Any advice what I'm doing wrong?

Here is my actual code (a .tsx file)


//refs

var React = refs.blib.React;
var ReactDOM = refs.blib.ReactDOM;
var Redux = refs.blib.Redux;
var ReactRedux = refs.blib.ReactRedux;
var Provider = ReactRedux.Provider;
//import {Provider} from "react-redux";

var ReactRouter = refs.blib.ReactRouter;
var IndexRoute = ReactRouter.IndexRoute;
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var Link = ReactRouter.Link;

const ReduxDevTools = refs.blib.ReduxDevTools;
//var DebugPanel = ReduxDevTools["DebugPanel"];
//var LogMonitor = ReduxDevTools["LogMonitor"];
//var DevTools = ReduxDevTools["DevTools"];

import History = refs.blib.History;

var ReduxSimpleRouter = refs.blib.ReduxSimpleRouter;
interface IAction {
    type: string;
    amount: number;
}

/**
 * ./actions/count.js
 */
module actions {
    export module count {
        export function increase(n: number) {
            return {
                type: constants.INCREASE,
                amount: n,
            };
        }
        export function decrease(n: number) {
            return {
                type: constants.DECREASE,
                amount: n,
            };
        }
    }
}

/**
 *  ./constants.js
 */
module constants {
    export const INCREASE = "INCREASE";
    export const DECREASE = "DECREASE";
}

/**
 * ./reducers/
 */
module reducers {

    /**
     *  ./reducers/count.js
     */
    export module count {
        export const initialState = { number: 1 };

        export function update(state = initialState, action: IAction) {
            if (action.type === constants.INCREASE) {
                return { number: state.number + action.amount };
            } else if (action.type === constants.DECREASE) {
                return { number: state.number - action.amount };
            }
            return state;
        }
    }
}
//

module components {
    /**
     *  ./components/app.js
     */

    interface _AppProps extends ReactRouter.RouteComponentProps<{}, { id: number }> {
        pushPath: (path: string, state?: any, avoidRouterUpdate?: boolean | {}) => void;
    }
    class _App extends React.Component<_AppProps, {}>{
        constructor(props) {
            super(props);
            this.state = {};
        }
        render() {
            return (
                <div>
                    <header>
                        Links:
                        {' '}
                            <ReactRouter.Link to="/">Home</ReactRouter.Link>
                            {' '}
                            <ReactRouter.Link to="/foo">Foo</ReactRouter.Link>
                            {' '}
                            <ReactRouter.Link to="/bar">Bar</ReactRouter.Link>
                        </header>
                          <div>
                            <button onClick={() => this.props.pushPath('/foo') }>Go to /foo</button>
                              </div>
                          <div style={{ marginTop: '1.5em' }}>{this.props.children}</div>
                    </div>
            );
        }
    }
    export var App: typeof _App = ReactRedux.connect(null, { pushPath: ReduxSimpleRouter.pushPath })(_App);

    /**
     *  ./components/bar.js
     */
    export class Bar extends React.Component<{}, {}>{
        render() {
            return (<div>And I am Bar!</div>);
        }
    }

    /**
     *  ./components/foo.js
     */
    export class Foo extends React.Component<{}, {}>{
        render() {
            return (<div>And I am Foo!</div>);
        }
    }

    /**
     *  ./components/home.js  ???  working????
     */

    interface _HomeProps extends ReactRouter.RouteComponentProps<{}, { id: number }> {
        number: number;
        increase: (n: number) => void;
        decrease: (n: number) => void;
    }
    var _increase = actions.count.increase;
    var _decrease = actions.count.decrease;
    class _Home extends React.Component<_HomeProps, { count: {number:number}}>{
        constructor(props) {
            super(props);
            this.state = { count: { number: 0 }};
        }
        render() {
            return (
                <div>
                    Some state changes:
                    {this.props.number}
                      <button onClick={() => this.props.increase(1) }>Increase</button>
                      <button onClick={() => this.props.decrease(1) }>Decrease</button>
                    </div>
            );
        }
    }
    export var Home: typeof _Home = ReactRedux.connect(
        state => (
            { number: state.count.number }
        ),
        { increase: _increase, decrease: _decrease }
    )(_Home);
}

var reducerObj = _.assign({}, reducers, { routing: ReduxSimpleRouter.routeReducer });
const reducer = Redux.combineReducers(reducerObj);

/////////// not working
const history = History.createHashHistory();
const middleware = (ReduxSimpleRouter as any).syncHistory(history); //.syncReduxAndRouter(history, store);
const finalCreateStore = Redux.compose(Redux.applyMiddleware(middleware), ReduxDevTools.devTools())(Redux.createStore);
const store = finalCreateStore(reducer);
middleware.syncHistoryToStore(store);

///////  from tutorial
//const store = Redux.createStore(reducer);
//const history = History.createHashHistory();
//ReduxSimpleRouter.syncReduxAndRouter(history, store);

ReactDOM.render(
    <Provider store={store}>
    <div>
      <Router history={history}>
        <Route path="/" component={components.App}>
          <IndexRoute component={components.Home}/>
          <Route path="foo" component={components.Foo}/>
          <Route path="bar" component={components.Bar}/>
            </Route>
          </Router>

        </div>
        </Provider>,
    document.getElementById('react-mount')
);
kimjoar commented 8 years ago

The problem is that you're following the example for master, which has changed considerably. Here's an example for 1.0.2: https://github.com/rackt/redux-simple-router/blob/1.0.2/examples/basic/app.js, which hopefully should work as expected for you :)

jasonswearingen commented 8 years ago

ok, thanks very much for the help!!!

jasonswearingen commented 8 years ago

fyi, besides looking at the wrong version of the example, my problem was

module reducers {

    /**
     *  ./reducers/count.js
     */
    export module count {
        export const initialState = { number: 1 };

        export function update(state = initialState, action: IAction) {
            if (action.type === constants.INCREASE) {
                return { number: state.number + action.amount };
            } else if (action.type === constants.DECREASE) {
                return { number: state.number - action.amount };
            }
            return state;
        }
    }
}

Since I'm putting all the code in one file, i should have exported the update() as count() instead:

module reducers {

    /**
     *  ./reducers/count.js
     */
    //export module count {
        const initialState = { number: 1 };

        export function count(state = initialState, action: IAction) {
            if (action.type === constants.INCREASE) {
                return { number: state.number + action.amount };
            } else if (action.type === constants.DECREASE) {
                return { number: state.number - action.amount };
            }
            return state;
        }
    //}
}

now all's working!