컴포넌트 비동기 렌더링의 기본

리액트 컴포넌트를 스플리팅 하는것도 이전에 notify 함수를 스플리팅 했던 방식과 똑같은 방식으로 할 수 있습니다.

한번 SplitMe 라는 컴포넌트를 만들어보세요:

src/SplitMe.js

import React from 'react';

const SplitMe = () => {
  return <div>리액트 컴포넌트를 코드스플리팅 하자.</div>;
};

export default SplitMe;

스플리팅 하고싶은 컴포넌트 내부에서는 딱히 특별한 작업을 하실 필요 없습니다. 그 대신에, 이 컴포넌트를 불러와서 사용하는 곳에서 import 를 통하여 비동기적으로 불러오면 됩니다.

이제, App 컴포넌트에서 리액트 로고를 누르게 됐을 때 SplitMe 컴포넌트를 불러와서 state 안에 넣어보겠습니다. 그리고 render 함수 내부에서는 SplitMe 컴포넌트가 성공적으로 불러와지고 난 다음에 컴포넌트에서 렌더링하도록 코드를 작성해보겠습니다.

src/App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  state = {
    SplitMe: null
  };
  handleClick = () => {
    import('./SplitMe').then(result => {
      this.setState({
        SplitMe: result.default
      });
    });
  };
  render() {
    const { SplitMe } = this.state;
    return (
      <div className="App">
        <img
          src={logo}
          className="App-logo"
          alt="logo"
          onClick={this.handleClick}
        />
        <p>Hello React!</p>
        {SplitMe && <SplitMe />}
      </div>
    );
  }
}

export default App;

위 코드는 async/await 를 사용하면 다음과 같이 작성 될 수 있습니다.

  handleClick = async () => {
    const result = await import('./SplitMe');
    this.setState({
      SplitMe: result.default
    });
  };

Edit splitting-sample

그런데, 모든 컴포넌트마다 state 를 만들어서 관리하기는 참 번거로울 것입니다. 때문에, 이를 함수화하여 더욱 쉽게 코드 스플리팅을 할 수 있도록 해주는 유틸 함수를 만들어서 코드 스플리팅을 해보겠습니다.

src 디렉토리에 withSplitting.js 이라는 파일을 만들어서 다음 함수를 작성해주세요:

src/withSplitting.js

import React, { Component } from 'react';

const withSplitting = getComponent => {
  // 여기서 getComponent 는 () => import('./SplitMe') 의 형태로 함수가 전달되야합니다.
  class WithSplitting extends Component {
    state = {
      Splitted: null
    };

    constructor(props) {
      super(props);
      getComponent().then(({ default: Splitted }) => {
        this.setState({
          Splitted
        });
      });
    }

    render() {
      const { Splitted } = this.state;
      if (!Splitted) {
        return null;
      }
      return <Splitted {...this.props} />;
    }
  }

  return WithSplitting;
};

export default withSplitting;

이 함수가 있다면, 더 이상 App.js 내부에서 상태안에 컴포넌트를 넣을 필요 없습니다. 그 대신에 불러오는 과정에서 이 함수를 통해 불러오시면 됩니다.

App 컴포넌트를 다음과 같이 수정해보세요:

src/App.js

import React, { Component } from 'react';
import withSplitting from './withSplitting';
import logo from './logo.svg';
import './App.css';

// 불러올 때 이렇게 withSplitting 으로 감싸서 불러옵니다.
const SplitMe = withSplitting(() => import('./SplitMe'));

class App extends Component {
  state = {
    visible: false
  };
  handleClick = () => {
    this.setState({
      visible: true
    });
  };
  render() {
    const { visible } = this.state;
    return (
      <div className="App">
        <img
          src={logo}
          className="App-logo"
          alt="logo"
          onClick={this.handleClick}
        />
        <p>Hello React!</p>
        {visible && <SplitMe />}
      </div>
    );
  }
}

export default App;

Edit splitting-sample

이전에는 우리가 state 안에 컴포넌트 자체를 담아줬엇지만, 이제는 visible 값에 따라 컴포넌트가 렌더링 될지말지 정하고있습니다.

이제는 우리가 단순히 렌더링만 해주면, 렌더링 되는 시점에서 자동으로 스플리팅된 파일의 로딩이 시작되고, 파일을 다 불러오고나서 컴포넌트가 렌더링이 됩니다.

results matching ""

    No results matching ""