totalnoob
totalnoob

Reputation: 2741

layouts flow in react router v4

My app currently has three components, User to view a person's profile, Self for a user to view their dashboard, notifications, and settings and a login page.

Both User and Self share common components Nav and Side, where User would pass the self object and call the fetchUser action from redux to Nav and Side, while Self would pass the user and self object along with calling the fetchSelf action.

User.js

class User extends React.Component {
    componentDidMount() {
        this.props.fetchUser(this.props.username);
    }

    render() {

        const { page, self, user } = this.props

        return (
            <main>

                <Nav 
                    self={self} 
                />

                <Side  
                    page={page} user={user} 
                />

                <div>
                     .....
                </div>

            </main>
        )
    }
}

const mapStateToProps = state => ({
    page: state.store.page,
    self: state.store.self
});

export default connect(mapStateToProps, {fetchUser})(User);

Self.js

class Self extends React.Component {
    componentDidMount() {
        this.props.fetchSelf();
    }

    render() {

        const { page, self } = this.props

        return (
            <main>

                <Nav 
                    self={self} 
                />

                <Side  
                    page={page} self={self} 
                />

                {
                    tab === 'Dashboard'
                    ? <Dashboard />
                    : tab === 'Notifications'
                        ? <Notifications />
                        : tab === 'Settings'
                            ? <Settings />
                            : null
                }

            </main>
        )
    }
}

const mapStateToProps = state => ({
    page: state.store.page,
    self: state.store.self
});

export default connect(mapStateToProps, {fetchSelf})(Self);

Login.js

class Login extends React.Component {
    .....

    handleChange = event => {
        .....
    }


    render() {

        return (
            <div id="login">
                .....
            </div>
    )
}

Side.js

const Side = (props) => {

    const { page, self, user } = props;

    return (

        <aside>
        {
            page === 'user'

            ?   <div>
                    <img src={'img/' + user.profile.avatar} alt={`${user.username}'s avatar`} />
            </div>

            :   <div>
                    <img src={'img/' + self.profile.avatar} alt={`${self.username}'s avatar`} />
                <div>   
        }
        </aside>
    )
}

What I'd like to do here is instead of using react-router like this

<BrowserRouter>
    <Switch>
        <Route path="/login" exact={true} component={Login} />  
        <Route path="/self" exact={true} component={Self} />    
        <Route path="/:username" component={User} />  
    </Switch>
</BrowserRouter>

I'd want to be able to do something like this instead

const LayoutForLoginAndSignup = (props) => {
    return (
        <div class="loginOrSignUp">
            <ComponentToBePassedIn />
        </div>
    )
}

class LayoutWithNavAndSide extends React.Component  {
    componentDidMount() {
        this.props.fetchSelf();
        // this.props.fetchUser('someusername')
    }

    render() {
        return (
            <main>
                <Nav self={this.props.self} />
                <Side page={this.props.page} self={this.props.self} user={this.props.user} />
                {Content of component that was passed in}
            </main>
        )
    }
}

const mapStateToProps = state => ({
    page: state.store.page,
    self: state.store.self,
    user: state.store.user
});

export default connect(mapStateToProps, {fetchUser, fetchSelf})(LayoutWithNavAndSide);



<BrowserRouter>
    <Switch>
        <LayoutForLoginAndSignup path="/login" exact={true} component={Login} />  
        <LayoutWithNavAndSide path='/self' component={Self} />
        <LayoutWithNavAndSide path="/:username" component={User} />  
    </Switch>
</BrowserRouter>

Here's where I get confused as I'm still new to react/redux/react router, how do I get the component of User or Self to show up in the layout? how do I get it to call fetchUser (on componentDidMount) only if someone is accessing /someuser vice versa with fetchSelf only when they goto the /self route? is it possible to do the layout as a function rather than a class?

Upvotes: 0

Views: 270

Answers (1)

Omar
Omar

Reputation: 3411

Create the component you will make a route for that contains both layouts and a condition.

const Layout = (props) => (
 {props.layout ? <SelfLayout /> : <UserLayout />}
)

Create two layouts.

const SelfLayout = () => ( <div> Self Layout </div> )

const UserLayout = () => ) <div> User Layout </div> )

Create your route.

<Route path={`/layout/${this.state.somelayout}`} render={() => <Layout 
layout={this.state.somelayout}/>} />

this.state.somelayout should be the conditional that decides which layout we are on and you can tailor it to the needs of your app this is just a guideline.

Upvotes: 2

Related Questions