LoginSignup
69
50

More than 3 years have passed since last update.

Reactで表示内容(headerとかfooterとか)のパーツ化・共通化

Last updated at Posted at 2019-12-12

いわゆるheader, main, footerとかで構成されるサイトにて、headerやfooterを共通パーツ化したい。
(逆に言えば、headerやfooterはそのままにmainの内容を切り替えたい)

スクリーンショット 2019-12-12 10.53.53.png

前提

  • ルーティングにはreact-router-domを利用する
  • よくcore-ui(React)を利用するので、そこでのやり方を踏襲

実装:基本編

App.js

App.jsですべてのルーティングを設定せず、レイアウトや認証が異なるといったレベルでルーティングを設定する。
基本的にDefaultコンポーネントに流す。

import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';

//screens
import Default from './screens/Default';
import Login from './screens/Login';

class App extends React.Component {
    render() {
        return (
            <BrowserRouter>
                <Switch>
                    <Route exact path="/login" component={Login} />
                    <Route path="/" component={Default} />
                </Switch>
            </BrowserRouter>
        );
    }
}

export default App;

Default.js

Default.jsにて基本レイアウトを適用し、変更される部分(ここではmain)をSwitchで囲み、ルーティングを設定する。

import React from 'react';
import { Switch, Route } from 'react-router-dom';

//screens
import Home from './Home';
import About from './About';
import Service from './Service';

class Default extends React.Component {
    render() {
        return (
            <div>
                <header style={styles.header}>head</header>
                <main style={styles.main}>
                    <Switch>
                        <Route exact path="/" component={Home} />
                        <Route path="/about" component={About} />
                        <Route path="/service" component={Service} />
                        <Route render={() => <p>not found!.</p>} />
                    </Switch>
                </main>
                <footer style={styles.footer}>footer</footer>
            </div>
        );
    }
}

export default Default;

//css
const styles = {
    header: {
        height: 100,
        background: "#ddd",
    },
    main: {
        height: 200,
    },
    footer: {
        height: 100,
        background: "#ddd",
    }
}

あとはそれぞれのページのレイアウトを行うだけ。

Home.js

Homeの内容。Homeと表示、リンクを設定してるだけ。

import React from 'react';
import { Link } from 'react-router-dom';

class Home extends React.Component {
    render() {
        return (
            <div>
                <p>Home</p>
                <p><Link to="/">Home</Link></p>
                <p><Link to="/about">About</Link></p>
                <p><Link to="/service">Service</Link></p>
            </div>
        );
    }
}

export default Home;

About.js

基本Homeと同じですが、一応。

import React from 'react';
import { Link } from 'react-router-dom';

class About extends React.Component {
    render() {
        return (
            <div>
                <p>About</p>
                <p><Link to="/">Home</Link></p>
                <p><Link to="/about">About</Link></p>
                <p><Link to="/service">Service</Link></p>
            </div>
        );
    }
}

export default About;

Service.js

基本Homeと同じですが、一応。

import React from 'react';
import { Link } from 'react-router-dom';

class Service extends React.Component {
    render() {
        return (
            <div>
                <p>Service</p>
                <p><Link to="/">Home</Link></p>
                <p><Link to="/about">About</Link></p>
                <p><Link to="/service">Service</Link></p>
            </div>
        );
    }
}

export default Service;

実装:応用編

コンポーネントが大量になると記述も大変だし、何より読み込みに時間がかかる。
core-uiのソースを見てるとroutesを変数化し、なおかつlazy()リードしている。

routes.js

まず、読み込みやルートの定義は別ファイル化して下記のように記述します(場所はとりあえずsrc直下に置いています)。

routes.js
import React from 'react';

const Home = React.lazy(() => import('./screens/Home'));
const About = React.lazy(() => import('./screens/About'));
const Service = React.lazy(() => import('./screens/Service'));

const routes = [
    { path: '/', exact: true, name: 'Home', component: Home },
    { path: '/about', exact: true, name: 'About', component: About },
    { path: '/service', exact: true, name: 'Service', component: Service },
]

export default routes;

Home.js

Home.js等でroutes.jsをimportし、ループにてRouteを設定しています。
なお、lazy()を使うと、読み込みの間表示するコンテンツの指定を<Suspense></Suspence>で行う必要があるようです。

Default.js
import React, { Suspense } from 'react';
import { Switch, Route } from 'react-router-dom';

import routes from '../routes';

class Default extends React.Component {

    loading = () => <div>Loading...</div>

    render() {
        return (
            <div>
                <header style={styles.header}>head</header>
                <main style={styles.main}>
                    <Suspense fallback={this.loading}>
                        <Switch>
                            {
                                routes.map((route, index) => (
                                    <Route
                                        key={index}
                                        path={route.path}
                                        exact={route.exact}
                                        name={route.name}
                                        render={props => (<route.component {...props} />)}
                                    />
                                ))
                            }
                            <Route render={() => <p>not found!.</p>} />
                        </Switch>
                    </Suspense>
                </main>
                <footer style={styles.footer}>footer</footer>
            </div>
        );
    }
}

export default Default;

const styles = {
    header: {
        height: 100,
        background: "#ddd",
    },
    main: {
        height: 200,
    },
    footer: {
        height: 100,
        background: "#ddd",
    }
}
69
50
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69
50