ReactでDynamc Import

手持ちのReact SPAが大きく育ってきたので、そろそろスリムにしていこうと思います。 準備 コンポーネントをならべる まずはインポートさせるためのコンポーネントを並べます。 そしてComponent1 ~ 3を別ファ […]

広告ここから
広告ここまで

目次

    手持ちのReact SPAが大きく育ってきたので、そろそろスリムにしていこうと思います。

    準備

    $ npx create-react-app react-dynamic-import
    $ cd react-dynamic-import
    $ yarn start

    コンポーネントをならべる

    まずはインポートさせるためのコンポーネントを並べます。

    import React, { Component } from 'react';
    import logo from './logo.svg';
    import './App.css';
    const Header = () => (
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Component1 />
        <Component2 />
        <Component3 />
      </header>
    )
    
    const Component1 = () => (
      <article>
        <h2>This is the <b>First</b> Component</h2>
      </article>
    )
    
    const Component2 = () => (
      <article>
        <h2>This is the <b>Secont</b> Component</h2>
      </article>
    )
    
    const Component3 = () => (
      <article>
        <h2>This is the <b>Third</b> Component</h2>
      </article>
    )
    
    class App extends Component {
      render() {
        return (
          <div className="App">
            <Header />
          </div>
        );
      }
    }
    
    export default App;

    そしてComponent1 ~ 3を別ファイルにしていきます。コンポーネント毎にファイルを切り出すとだいたいこうなります。

    $ tree src/
    src/
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── Component1.jsx
    ├── Component2.jsx
    ├── Component3.jsx
    ├── Header.jsx
    ├── index.css
    ├── index.js
    ├── logo.svg
    └── serviceWorker.js

    Dynamic Importする

    それでは作ったファイルをDynamic Import化します。

    import React from 'react';
    import logo from './logo.svg';
    import Component1 from './Component1'
    import Component2 from './Component2'
    import Component3 from './Component3'
    
    class Header extends React.Component {
      render() {
        return (
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <Component1 />
            <Component2 />
            <Component3 />
          </header>
        )
      }
    }
    
    export default Header

    Dynamic Importでは、コンポーネントをstateにもたせます。そのため、まずは以下のような実装にしましょう。

    import React from 'react';
    import logo from './logo.svg';
    
    class Header extends React.Component {
      state = {
        component1: null,
        component2: null,
        component3: null,
      }
      async componentDidMount() {
        // import the components
      }
      render() {
        const { component1, component2, component3} = this.state
        return (
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            {component1 || <div>...</div>}
            {component2 || <div>...</div>}
            {component3 || <div>...</div>}
          </header>
        )
      }
    }
    
    export default Header

    componentDidMount()でマウントされてからコンポーネントを読むようにします。

    
      async componentDidMount() {
        const { default: Component1 } = await import('./Component1');
        const { default: Component2 } = await import('./Component2');
        const { default: Component3 } = await import('./Component3');
        this.setState({
          component1: Component1(),
          component2: Component2(),
          component3: Component3(),
        });
      }

    非同期でimportしてsetStateする形です。簡単ですね。

    ボタンイベントでロードしてみる

    ようは何かしらの形でimportを非同期実行して、stateにいれてやればOKということですね。なのでonClickイベントを使って「ボタンをクリックした時だけロードする」ということもできます。

    import React from 'react';
    import logo from './logo.svg';
    
    class Header extends React.Component {
      state = {
        component1: null,
        component2: null,
        component3: null,
      }
      async componentDidMount() {
        const { default: Component1 } = await import('./Component1');
        const { default: Component2 } = await import('./Component2');
        this.setState({
          component1: Component1(),
          component2: Component2(),
        });
      }
      handleClick = async (e) => {
        e.preventDefault()
        const { component3 } = this.state
        if (!component3 || component3 === null) {
          const { default: Component3 } = await import('./Component3');
          this.setState({
            component3: Component3(),
          });
          return
        }
        this.setState({
          component3: null,
        });
      }
      render() {
        const { component1, component2, component3} = this.state
        return (
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" onClick={this.handleClick} />
            {component1 || <div>...</div>}
            {component2 || <div>...</div>}
            {component3 || <div>画像をクリックすると表示されます。</div>}
          </header>
        )
      }
    }
    
    export default Header
    

    こうすることでロゴ画像をクリックするたびにcomponent3を表示したり削除したりできます。

    Next

    Dynamic Importの威力がでるのは、おそらくReact Routerと組み合わせたときかなと思っています。表示に関係のないコンポーネントをよまなくすればロード短縮になりますので。

    ということで次回はReact Routerがある状況にてトライしてみます。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark