Search code examples
rect

Loading state from parent route component in react


I have this kind of situation in my react router:

root.js

<Route path="job-opportunity" component={Opportunity} >
    <Route path=":opportunitySlug" />
</Route>

When I open domain.com/job-opportunity everything works fine But when I hit child route domain.com/job-opportunity/some-slug

It doesn't load some constructor state from Opportunity component that I am using in child component.

Let me show you my Opportunity component:

class Opportunity extends React.Component{
    constructor(props){
        super(props);

        this.loadOpportunities = this.loadOpportunities.bind(this);

        this.state = {
            'opportunities' : []
        };
        this.loadOpportunities();
    }
    loadOpportunities(){
        $.get($('.api_router_load_opportunities').val(), function(data){
            this.setState({'opportunities' : data});
        }.bind(this));
    }
    render() {
        return (
            <div>
                <h1>Layout!</h1>
                <Content
                    opportunities={this.state.opportunities}
                    loggedUser={this.props.loggedUser}
                    opportunitySlug={this.props.params.opportunitySlug}
                    />
            </div>
        )
    }
} 

function Content(props){
    const opportunitySlug = props.opportunitySlug;
    if(opportunitySlug){
        return <SingleOpportunity
            opportunities={props.opportunities}
            loggedUser={props.loggedUser}
            opportunitySlug={opportunitySlug}
            />;
    }else{
        return <ListOpportunity
            opportunities={props.opportunities}
            loggedUser={props.loggedUser}
            />;
    }
}

export default Opportunity;

Basically when I hit domain.com/job-opportunity then navigate from link in browser everything works fine even in this route:

domain.com/job-opportunity/some-slug

But when I hit directly in browser domain.com/job-opportunity/some-slug

It brokes because I am rendering in SingleOpportunity this.props.opportunities[this.props.opportunitySlug].name


Solution

  • I found some solution:

    if(this.props.opportunities.length != 0){
                const opportunity = this.props.opportunities[this.props.opportunitySlug];
                return (
                    <div key={this.props.opportunitySlug}>
                        <p><strong>Name:</strong> {opportunity.name}</p>
                        <p><strong>Description:</strong> {opportunity.description}</p>
                    </div>
                );
            }else{
                return null;
            }
    

    If you are using some props or state after initial load, it will render multiple times that and at the last render it will have your props or states loaded! So you need to handle you render functions by checking is your state or props ready.