0

brand new to react so heads up

Im doing the catch of the day tutorial and am on the step where you integrate routes to redirect urls on button clicks. I set it up how the tutorial says:

    var React = require('react');
var ReactDOM = require('react-dom');

var ReactRouter = require('react-router');
var Router  = ReactRouter.Router;
var Route = ReactRouter.Route;
var History = ReactRouter.History;

var createBrowserHistory = require('history/lib/createBrowserHistory');

var h = require('./helpers');
/*
  App
*/

var App = React.createClass({

  render : function() {
    return (
      <div className="catch-of-the-day">
        <div className="menu">
          <Header tagline="Fresh Seafood Market" />
        </div>
        <Order/>
        <Inventory/>
      </div>
    )
  }
});

/*
  Header
  <Header/>
*/
var Header = React.createClass({
  render : function() {
    return (
      <header className="top">
        <h1>Catch
          <span className="ofThe">
            <span className="of">of</span>
            <span className="the">the</span>
          </span>
          Day</h1>
        <h3 className="tagline"><span>{this.props.tagline}</span></h3>
      </header>
    );
  }
})

/*
  Order
  <Order/>
*/
var Order = React.createClass({
  render : function() {
    return (
      <p>Order</p>
    );
  }
})

/*
  Inventory
  <Inventory/>
*/
var Inventory = React.createClass({
  render : function() {
    return (
      <p>Inventory</p>
    );
  }
})


/*
  StorePicker
  This will let us make <StorePicker/>
*/

var StorePicker = React.createClass({
  mixins : [History],
  goToStore : function(event) {
    event.preventDefault();
    // get the data from the input
    var storeId = this.refs.storeId.value;
    this.history.pushState(null, '/store/' + storeId);
  },
  render : function() {
    return (
      <form className="store-selector" onSubmit={this.goToStore}>
        <h2>Please Enter A Store</h2>
        <input type="text" ref="storeId" defaultValue={h.getFunName()} required />
        <input type="Submit" />
      </form>
    );
  }

});

/*
  Not Found
*/

var NotFound = React.createClass({
  render : function() {
    return <h1>Not Found! 404</h1>
  }
});


/*
  Routes
*/

var routes = (
  <Router history={createBrowserHistory()}>
    <Route path="/" component={StorePicker}/>
    <Route path="/store/:storeId" component={App}/>
    <Route path="*" component={NotFound}/>
  </Router>
)

ReactDOM.render(routes, document.querySelector('#main'));

but it does not redirect on button press, I get this error in my console:

uncaught TypeError: history.push is not a function

Tried to move away from the mixin which is depreciated following the link given to me by @ManoloSantos

this is my updated code which runs with the same error:

var React = require('react');
var ReactDOM = require('react-dom');

var ReactRouter = require('react-router');
var Route = ReactRouter.Route;
var History = ReactRouter.History;
import { Router, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
var createBrowserHistory = require('history/lib/createBrowserHistory');
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false })
var h = require('./helpers');
/*
  App
*/

var App = React.createClass({

  render : function() {
    return (
      <div className="catch-of-the-day">
        <div className="menu">
          <Header tagline="Fresh Seafood Market" />
        </div>
        <Order/>
        <Inventory/>
      </div>
    )
  }
});

/*
  Header
  <Header/>
*/
var Header = React.createClass({
  render : function() {
    return (
      <header className="top">
        <h1>Catch
          <span className="ofThe">
            <span className="of">of</span>
            <span className="the">the</span>
          </span>
          Day</h1>
        <h3 className="tagline"><span>{this.props.tagline}</span></h3>
      </header>
    );
  }
})

/*
  Order
  <Order/>
*/
var Order = React.createClass({
  render : function() {
    return (
      <p>Order</p>
    );
  }
})

/*
  Inventory
  <Inventory/>
*/
var Inventory = React.createClass({
  render : function() {
    return (
      <p>Inventory</p>
    );
  }
})


/*
  StorePicker
  This will let us make <StorePicker/>
*/

var StorePicker = React.createClass({
  contextTypes: {
    router: React.PropTypes.object.isRequired
  },
  goToStore : function(event) {
    event.preventDefault();
    // get the data from the input
    var storeId = this.refs.storeId.value;
    this.context.router.push(null, '/store/' + storeId);
  },
  render : function() {
    return (
      <form className="store-selector" onSubmit={this.goToStore}>
        <h2>Please Enter A Store</h2>
        <input type="text" ref="storeId" defaultValue={h.getFunName()} required />
        <input type="Submit" />
      </form>
    );
  }

});

/*
  Not Found
*/

var NotFound = React.createClass({
  render : function() {
    return <h1>Not Found! 404</h1>
  }
});


/*
  Routes
*/

var routes = (
  <Router history={appHistory}>
    <Route path="/" component={StorePicker}/>
    <Route path="/store/:storeId" component={App}/>
    <Route path="*" component={NotFound}/>
  </Router>
)

ReactDOM.render(routes, document.querySelector('#main'));

THIS FIXED IT:

var React = require('react');
var ReactDOM = require('react-dom');

var ReactRouter = require('react-router');
var Router  = ReactRouter.Router;
var Route = ReactRouter.Route;
import { browserHistory, IndexRoute, useRouterHistory } from 'react-router'
import { createHistory } from 'history'
var h = require('./helpers');


const history = useRouterHistory(createHistory)({
  basename: '/'
})


/*
  App
*/

var App = React.createClass({

  render : function() {
    return (
      <div className="catch-of-the-day">
        <div className="menu">
          <Header tagline="Fresh Seafood Market" />
        </div>
        <Order/>
        <Inventory/>
      </div>
    )
  }
});

/*
  Header
  <Header/>
*/
var Header = React.createClass({
  render : function() {
    return (
      <header className="top">
        <h1>Catch
          <span className="ofThe">
            <span className="of">of</span>
            <span className="the">the</span>
          </span>
          Day</h1>
        <h3 className="tagline"><span>{this.props.tagline}</span></h3>
      </header>
    )
  }
})

/*
  Order
  <Order/>
*/
var Order = React.createClass({
  render : function() {
    return (
      <p>Order</p>
    )
  }
})

/*
  Inventory
  <Inventory/>
*/
var Inventory = React.createClass({
  render : function() {
    return (
      <p>Inventory</p>
    )
  }
})


/*
  StorePicker
  This will let us make <StorePicker/>
*/

var StorePicker = React.createClass({
  goToStore : function(event) {

    event.preventDefault();
    // get the data from the input
    var storeId = this.refs.storeId.value;
    browserHistory.push('/store/' + storeId);
  },
  render : function() {
    return (
      <form className="store-selector" onSubmit={this.goToStore}>
        <h2>Please Enter A Store</h2>
        <input type="text" ref="storeId" defaultValue={h.getFunName()} required />
        <input type="submit" />
      </form>
    )
  }

});

/*
  Not Found
*/

var NotFound = React.createClass({
  render : function() {
    return <h1>Not Found!</h1>
  }
});


/*
  Routes
*/

var routes = (
  <Router history={browserHistory}>
    <Route path="/" component={StorePicker}/>
    <Route path="/store/:storeId" component={App}/>
    <Route path="*" component={NotFound}/>
  </Router>
)

ReactDOM.render(routes, document.querySelector('#main'));
5
  • Which version of react-router are you using? The use of mixins has been discouraged for a while. Commented Aug 19, 2016 at 20:55
  • @ManoloSantos "react-router": "^2.6.1", Commented Aug 19, 2016 at 20:56
  • I have updated my answer to indicate an easier way to get the router from the context. Commented Aug 19, 2016 at 21:41
  • i don't know mixin thing but i think you should use this.props.history.pushState, you are missing props Commented Aug 19, 2016 at 21:49
  • Oh, and you have to remove the null in the call to push. Commented Aug 19, 2016 at 22:38

1 Answer 1

1

You are using a deprecated way for navigating. In this page you have an upgrade guide to migrate from mixins. I paste here the relevant part.

// v2.0.0
// You have a couple options:
// 1) Use context.router (especially if on the server)
const DeepComponent = React.createClass({
  contextTypes: {
    router: React.PropTypes.object.isRequired
  },
  handleSubmit() {
    this.context.router.push(...)
  }
}

// 2) Use the singleton history
import { browserHistory } from 'react-router'
const DeepComponent = React.createClass({
  handleSubmit() {
    browserHistory.push(...)
  }
}

Edit: It seems that from v2.4 there is a HoC that simplifies the acquisition of the router from the context.

Sign up to request clarification or add additional context in comments.

3 Comments

tried to shift to that but get the same error, am I doing something wrong? I updated my above post with new code
Sorry, I had added a wrong addendum to my question. I have rollbacked it.
Im sorry and i appreciate all the help, but how do I impliment that HoC into what I have? everything I've tried doesn;t fix it so I must be off somewhere

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.