简体   繁体   中英

React Router - withRouter component that renders even if no match

My use case is this: I have a component that I want to control the url. It will have 3 "selects" in it - one for selecting a customer, one for selecting a courier, and one for selecting a service. It should (a) react to the route correctly by rendering the correct one of those three options IF provided, (b) render even if those parameters aren't there , and (c) change the route appropriately when an option is clicked

Here's my base App.js which illustrates the containing route and how I'm expecting the url to look:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import autoBind from 'react-autobind';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import { BrowserRouter, Route, NavLink } from "react-router-dom";
import CcsSelect from './customer-prices/ccs-select';

class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            customers: window._customers_json || [],
            couriers: window._couriers_json || [],
            services: window._services_json || []
        };

        autoBind(this);
    }

    render() {
        return (
            <>
                <ToastContainer />
                <BrowserRouter basename="/app/customer-prices">
                    <Route exact={false} path="/:customerid/:courierid/:serviceid">
                        <CcsSelect/>
                    </Route>

                    <h1>I'm in react! Hi Mom</h1>
                </BrowserRouter>
            </>
        )
    }
}


const $container = document.getElementById('react-container');
if ($container) {
    ReactDOM.render(<App />, $container);
}

And here's my ccs-select.jsx file, which I'm expecting to render inside the Route EVEN IF there are no parameters:

import React, { Component } from 'react';
import { BrowserRouter, Route, withRouter } from "react-router-dom";
import autoBind from 'react-autobind';

class CcsSelect extends Component {
    constructor(props) {
        super(props);

        console.log(props);

        this.state = {
            customer: props.match.params.customerid,
            courier: props.match.params.courierid,
            service: props.match.params.serviceid
        };

        autoBind(this);
    }

    render() {
        return (
            <div>
                <p>I'm in the router</p>
                <p>customer id: {this.state.customer}</p>
                <p>courier id: {this.state.courier}</p>
                <p>service id: {this.state.service}</p>
            </div>

        )
    }
}

export default withRouter(CcsSelect);

Now at the moment obviously CssSelect doesn't change the path - I'm not dealing with that yet. It appropriately renders when I set the path to, say, /app/customer-prices/x/y/z , including setting the state variables and rendering the x, y, z strings. But it's not rendering when I use the url /app/customer-prices/ -- whereas what I'm wanting is for it to render and have the state representing each url parameter to be null if it's not supplied.

What's the best way to get what I'm looking for?

Currently, you only have one route with the path /:customerid/:courierid/:serviceid .

You have to create a new route with the path / and the exact param set to true to handle the url /app/customer-prices/ . In this route, you can have the same children as the other route, it's not a problem.

Here an example:

<BrowserRouter basename="/app/customer-prices">
  <Route exact={false} path="/:customerid/:courierid/:serviceid">
    <CcsSelect/>
  </Route>
  <Route exact path="/">
    <CcsSelectOrAnotherComponent/>
  </Route>

  <h1>I'm in react! Hi Mom</h1>
</BrowserRouter>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM