Bryce Martin
Bryce Martin

Reputation: 129

react-router hashHistory push changes URL only

I'm having trouble getting my react app to load the component of a child route. The URL changes when I do this.context.router.push('/url') but the component that is named to load for that route is not loading. I have this working in another component but this one won't work. The only thing I can see that is different is that the one that doesn't work is 1 level deeper in the routes tree than the one that works.
I have look all over the place on SO as well as the react-router documentation and various tutorials to see if I could find anything that would give me a clue, but have come up empty. Here is the relevant code.

client.js -(app.js for most people)

<Router history={hashHistory}>
    <Route path="/" component={Layout}>
        <IndexRoute component={Dashboard}></IndexRoute>
        <Route path="Login" component={Login}></Route>
        <Route path="accounting">
            <Route path="authorize-orders" component={AuthorizeOrders}></Route>
            <Route path="authorize-card" component={Sale}>
                <Route path="select-invoices" component={SaleSelectInvoices}></Route>
            </Route>
        </Route>
    </Route>
</Router>

SaleSelectInvoices.js

    class SaleSelectInvoices extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            bearer: AppStore.getBearer(),
            customerInvoices: null
        }
    }
    render() {
        if (!this.state.customerInvoices) {
            return (<div>Loading...</div>);
        }
        return (
            <div>
                <h1>Authorize Credit Card Payment</h1>
                <h2>Select Invoices</h2>
                <div class="row">
                    <div class="col-md-1">Select</div>
                    <div class="col-md-3">Invoice #</div>
                    <div class="col-md-4">Amount</div>
                    <div class="col-md-4">Charge Amount</div>
                </div>

            </div>

        );
    }
}
export default SaleSelectInvoices;

In a click event handler function I do the following.

this.context.router.push('/accounting/authorize-card/select-invoices');

I do the context reference...

Sale.contextTypes = {
    router: React.PropTypes.object.isRequired
}

Sale.js

render() {
    var opts = {};
    if (!this.state.formIsValid) {
        opts['disabled'] = 'disabled';
    }
    return (
        <div>
            <h1>Authorize Credit Card Payment</h1>

            <h2>Select Customer</h2>            
            <form>
                <input ref="customerNumber" name="customer" 
                onChange={this.handleCustomerInputChange} 
                onBlur={this.validateCustomerNumber} 
                min="86" max="999999" type="numeric" class="customerNumber" />                        
                <button {...opts} onClick={this.handleCustomerSelect}>Next</button>
            </form>
        </div>
    );
}

So, like I said at the beginning, the URL changes to the proper route, but the page does not render the SaleSelectInvoices component.. I still see the Sale component. The browser console does not have any errors listed either.

Upvotes: 1

Views: 2527

Answers (1)

Paul S
Paul S

Reputation: 36787

The select-invoices path is a child route of authorize-card, so the <SaleSelectInvoices> component is rendered as a child of the <Sale> component. This means that you will need to include this.props.children in your <Sale> component's render method.

If you do not want to do this, but you want the select-invoices route to be a child of authorize-card, you can declare <Sale> as an <IndexRoute> and use a holder component for the two..

<Route path="authorize-card" component={SaleHolder}>
  <IndexRoute component={Sale} />
  <Route path="select-invoices" component={SaleSelectInvoices}></Route>
</Route>

The <SaleHolder> will just return its children prop.

const SaleHolder = (props) => {
  return props.children;
}

Upvotes: 1

Related Questions