0

I'm trying to pass three URL params to React Component. Here's what I've done:

App.js:

<Route path="/details/:id(/:query)(/:type)" handler={DishDetails}/>

DishDetails.js:

class DishDetails extends Component {
    constructor(props) {
        super(props);
        console.log("props in DishDetails: ")
        console.log(props);
        this.state = {
            id: props.match.params.id,
            status: "INITIAL",
            query: props.match.params.query,
            type: props.match.params.type,
        };
    }

render() {
    let ingredientsList;
    switch(this.state.status){
        case "INITIAL":
            return (
                <p>Loading...</p>
            );
            break;
        case "ERROR":
            return (
                <p>An error has occurred, please refresh the page</p>
            );
    }
    return (
        //Only come here if we get a successful response
        <div id="details">
            <div className="dishdetails">
                <h3 id="dishtitle" className="dishtitle">{this.state.title}</h3>
                <img id="dishimg" className="dishimg" src={this.state.img}/>
                <div id="dishtext" className="dishtext col-lg-12 col-md-12 col-sm-12 col-xs-12">
                    {this.state.dishText}
                </div>
                <div className="back-to-search">
                    <Link to="/search" params={{query:this.state.query, type:this.state.type}}><button id="details-backbutton" className="btn btn-default" type="button">Back to Search</button></Link>
                </div>
            </div>
            <Instructions instructions={this.state.instructions} />
            <IngredientsList ingredients={this.state.ingredients} />
            <Sidebar />
        </div>
    );
}

}

then I go to http://localhost:3000/details/77/myQuery/myType. 2 Problems are then clear: 1. When I look in the console for the props output, there is nothing there. 2. Nothing renders.

Things I've tried:

  1. Changing handler in the route to component.
  2. Changing to only 1 param like http://localhost:3000/details/77

Nothing changes.

EDIT:

I tried changing my code to:

class DishDetails extends Component {
    constructor(props) {
        super(props);
//        const dish = props.model.getDish(1);
        // do api call
        console.log("props in DishDetails: ")
        console.log(props);
        this.state = {
            id: props.match.params.id,
        };
    }
    render() {
        switch(this.state.status){
            case "INITIAL":
                return (
                    <p>Loading...</p>
                );
            case "ERROR":
                return (
                    <p>An error has occurred, please refresh the page</p>
                );
        }
        return (
            //Only come here if we get a successful response
            <div id="details">
                <div className="dishdetails">
                    <h3 id="dishtitle" className="dishtitle">{this.state.title}</h3>
                    <img alt="details-img" id="dishimg" className="dishimg" src={this.state.img}/>
                    <div id="dishtext" className="dishtext col-lg-12 col-md-12 col-sm-12 col-xs-12">
                        {this.state.dishText}
                    </div>
                    <div className="back-to-search">
                        <Link to={{
                            pathname:"/search",
                            state: {
                                params: {
                                    query:this.props.query,
                                    type:this.props.type,
                                }
                            },
                            }}>
                            <button id="details-backbutton" className="btn btn-default" type="button">Back to Search</button>
                            </Link>
                    </div>
                </div>
                <Instructions instructions={this.state.instructions} />
                <IngredientsList ingredients={this.state.ingredients} />
                <Sidebar />
            </div>
        );
    }
}

But the problems persist.

Sahand
  • 7,980
  • 23
  • 69
  • 137

1 Answers1

0

You set the state from the match props in the constructor which is called only on the initial render. Since the state is not modified and is directly derivable from props, you could use the props directly in render.

Secondly, you need to pass the params to /search link component a little differently . Check out this question

How to pass params with history.push in react-router v4?

class DishDetails extends Component {
    constructor(props) {
        super(props);
        console.log("props in DishDetails: ")
        console.log(props);
        this.state = {
            status: "INITIAL",
        };
    }

    render() {
        let ingredientsList;
        switch(this.state.status){
            case "INITIAL":
                return (
                    <p>Loading...</p>
                );
                break;
            case "ERROR":
                return (
                    <p>An error has occurred, please refresh the page</p>
                );
        }
        return (
            //Only come here if we get a successful response
            <div id="details">
                <div className="dishdetails">
                    <h3 id="dishtitle" className="dishtitle">{this.state.title}</h3>
                    <img id="dishimg" className="dishimg" src={this.state.img}/>
                    <div id="dishtext" className="dishtext col-lg-12 col-md-12 col-sm-12 col-xs-12">
                        {this.state.dishText}
                    </div>
                    <div className="back-to-search">
                        <Link to={{ 
                             pathname: "/search", 
                             state: { 
                                params: { 
                                    query:this.props.query,
                                    type:this.props.type
                                }
                             }
                          }}>
                          <button id="details-backbutton" className="btn btn-default" type="button">Back to Search</button></Link>
                    </div>
                </div>
                <Instructions instructions={this.state.instructions} />
                <IngredientsList ingredients={this.state.ingredients} />
                <Sidebar />
            </div>
        );
    }
}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Hello, thanks for your suggestions. I implemented them all, but the same problem persists. Nothing is shown. – Sahand Mar 30 '18 at 12:27
  • What do you mean by nothing is shown, are you not getting the params in render or the data is not fetched. Can you explain the behaviour a bit – Shubham Khatri Mar 30 '18 at 13:13
  • It seems like the DishDetails class is not even run. Console doesn't output any props like I've told it to in `DishDetails.constructor()`, it doesn't output anything at all, not even `"props in DishDetails: "`. Also, nothing is rendered on the screen, it's blank – Sahand Mar 30 '18 at 13:23