Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render child component via React-router

So I've been struggling with this code. I have a component which accepts a child as a prop, and it is supposed to be the base of all the pages I host.

Base.jsx :

import React from 'react';
import PropTypes from 'prop-types';
import { Link, NavLink } from 'react-router-dom';

const Base = ({ child }) => (
    <div>
        <div className="top-bar">
            <div className="top-bar-left">
                <NavLink to="/">React App</NavLink>
            </div>

            <div className="top-bar-right">
                <Link to="/login">Log in</Link>
            </div>

        </div>

        {child.render()} // HERE IS THE CHILD TO RENDER

    </div>
);

Base.propTypes = {
    child: PropTypes.object.isRequired
};
export default Base;

Then, in app.jsx, where lies the ReactDom.render(), I have this :

import React from 'react';
import ReactDom from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
import LoginPag from './components/LoginPag.jsx';
import Base from './components/Base.jsx';
import HomePage from './components/HomePage.jsx';

// for MaterialUI to work properly
injectTapEventPlugin();

const TestLogin = (props) => {
    return (<Base child={LoginPag} />);
};

const TestBase = (props) => {
    return(<Base child={HomePage}/>)
};

ReactDom.render((<BrowserRouter><MuiThemeProvider muiTheme={getMuiTheme()}>
    <div>
    <Switch>
        <Route exact path="/" component={TestBase} />
        <Route exact path="/login" component={TestLogin}/>
    </Switch>
    </div>
    </MuiThemeProvider>
</BrowserRouter>), document.getElementById('react-app'));

Finally, HomePage and LoginPag look alike and here's the HomePage.jsx :

import React from 'react';
import { Card, CardTitle } from 'material-ui/Card';

const HomePage = {
    render() {
        return (<Card className="container">
            <CardTitle title="React Application" subtitle="This is the home page." />
        </Card>);
    }
};

export default HomePage;

My question now is : Isn't it possible to get rid of these abstractions TestLogin and TestBase ?

My final goal is to have something like this :

<Route exact path="/" component={Base(HomePage)} />, that is to say getting rid of the abstraction layer and directly render this in one line.

Thanks in advance.

EDIT: Thanks to anuragasaurus, I could achieve what I wanted. Can I do it with a class as well ? The class is declared as class LoginPage extends React.Component and has a render() method.

like image 661
Gaëtan Boyals Avatar asked Feb 22 '26 16:02

Gaëtan Boyals


2 Answers

You can use render to display your component inline,

<Route exact path="/" render={()=><Base child={HomePage} />} />
<Route exact path="/login" render={()=><Base child={LoginPage} />}/>
like image 81
Anurag Awasthi Avatar answered Feb 24 '26 05:02

Anurag Awasthi


With a simple object AND a class:

const Base = ({ child }) => (
    <div>
        <div className="top-bar">
            <div className="top-bar-left">
                <NavLink to="/">React App</NavLink>
            </div>

            <div className="top-bar-right">
                <Link to="/login">Log in</Link>
            </div>

        </div>

        {child}

    </div>
);

And

const TestLogin = (props) => {
    return (<Base child={<LoginPage/>} />);
};

const TestBase = (props) => {
    return(<Base child={<HomePage}/>/>)
};

To answer for the entire question :

<Route exact path="/" render={()=><Base child={<HomePage/>} />} />
<Route exact path="/login" render={()=><Base child={<LoginPage/>} />}/>
like image 36
Fuego Avatar answered Feb 24 '26 04:02

Fuego



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!