Changing components based on url with react router

13,986

I feel what you are doing is perfectly fine. You are on the right path.

There's a combination of APIs that React provides you with that will take care of exactly what you're not certain about of how to achieve ( way to pass props to components rendered by this.props.children )

First, you need to take a look at cloneElement

It will basically take a React element, clone it, and return another with props that you can change, alter or replace entirely based on your needs.

Furthermore, combine it with the Children Utilities - loop through the children that were provided to your top level component and make the necessary changes to each element individually.

A proposed sample usage could be as simple as

<div className='main-content'>
    {React.children.map(this.props.children, (child, index) => {
       //Get props of child
       const childProps = child.props;

       //do whatever else you need, create some new props, change existing ones
       //store them in variables

       return React.cloneElement(child, {
           ...childProps, //these are the old props if you don't want them changed
           ...someNewProps,
           someOldPropOverwritten, //overwrite some old the old props 
       });
     )}
</div>

Use these tools to create truly generic and re-usable components, anywhere. More commonly used utilities from Children are map, forEach and toArray. Each with their own respective goals.

Hope this helps.

Share:
13,986
jmknoll
Author by

jmknoll

Web and mobile development (Rails, React, React Native, iOS), product development and strategy. Lead developer and product guy at Mentorverse | Online Admissions Counseling. Current interests - Elixir, Ethereum From Philadelphia. Currently based in Shanghai. Shoot me a message to talk crypto, mobile, or China tech. Always open to discussing new opportunities. Write me at jameson.knoll at gmail

Updated on July 17, 2022

Comments

  • jmknoll
    jmknoll almost 2 years

    This is more of an architectural question regarding react than a specific issue, but what is considered best practice for managing state/props with a layout component and a several child components which are rendered based on the url?

    Note: I'm aware that similar questions have been asked, but this is a little bit different. [How to update ReactJS component based on URL / path with React-Router

    Lets say I have something like the following code: A profile page (main layout view) with navigation links for profile sub-sections (settings, preferences, account details, etc), and a main panel where each of the sub-section is rendered.

    So currently I would have something like this: my router routes.js

    <Router history={browserHistory}>
      <Route path='/profile' component={Profile} >
        <IndexRoute component={Summary} />
        <Route path='/profile/settings' component={Settings} />
        <Route path='/profile/account' component={Account} />
        <Route path='/profile/preferences' component={Preferences} />
      </Route>
    </Router>
    

    and a stripped down version of my profile layout component profile.js

    class Profile extends React.Component {
    
      constructor(props) {
        super(props)
      }
    
      render(){
    
        let pathName = this.props.location.pathname;
    
        return(
          <div className='container profile-page'>
            <div className='side-nav'>
              <ul>
                <li><Link to='/profile'>Summary</Link></li>
                <li><Link to='/profile/settings'>Settings</Link></li>
                <li><Link to='/profile/account'>My Account</Link></li>
                <li><Link to='/profile/preferences'>Preferences</Link></li>
              </ul>
            </div>
            <div className='main-content'>
             {this.props.children}
            </div>
          </div>
        )
      }
    }
    
    export default Profile;
    

    So this kind of works. The child components will render based on the url. But then how do I manage state and props? The way I understand React and Flux, I want the Profile component to manage state and listen to changes on my stores, and to propagate those changes to its children. Is this correct?

    My problem is that there doesn't seem to be an intuitive way to pass props to components rendered by this.props.children, which makes me feel like my current architecture and/or understanding of flux is not correct.

    A bit of guidance would be much appreciated.

  • jmknoll
    jmknoll about 8 years
    Okay, this makes a lot more sense now. Thank you very much for the comprehensive answer.
  • Elod Szopos
    Elod Szopos about 8 years
    Most welcome, that's the purpose of the board. Hopefully it'll help others too. Kudos for a good question, hardly any these days.