LoginSignup
5
2

More than 3 years have passed since last update.

React初心者覚書 コンポジション vs 継承

Posted at

コンポジション vs 継承
を参考に初心者がわからないけど覚書を書いています。

React は強力なコンポジションモデルを備えており、コンポーネント間のコードの再利用には継承よりもコンポジションをお勧めしています。

コンポジションって何?

参考
- Reactにおけるコンポジションとは?
Reactでアプリを作成する場合、ヘッダ・フッタ・サイドバー・メニューなどの部品をコンポーネントによって作成します。Reactでアプリを作成する際には、コンポーネントをどのように分割して構成するかが重要となります。これを「Reactコンポーネントのコンポジション」と呼びます。
(わかりやすい解説)
- ひとつひとつの Reactコンポーネントは関数のようなものですが、それらを組み合わせてコンポジションによってカスタマイズできる

  • どんな子要素が入るのか決まっていないコンポーネントがある場合
    • children という特別な機能を持つ props を使うことができます。childrenは 子要素を渡すための専用の props
    • childrenに任せた!みたいな感じ?

子要素の出力 (Containment)

  • コンポーネントの中には事前には子要素を知らないものもある。“入れ物(Sidebar,Dialogなど)” をあらわすコンポーネントではよく使われる
  • JSX タグの内側のあらゆる要素は FancyBorder に children という props として渡される
index.js

import React from 'react';
import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import './index.css';

function FancyBorder(props) {
  return(
    <div className ={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}

function Dialog(props) {
  return(
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog(){
  return(
    <Dialog
      title="ようこそ!"
      message="you are welcome!!" />
  );
}

ReactDOM.render(
  <WelcomeDialog />,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
index.css
.FancyBorder{
  padding: 10px;
  border: solid 10px;
  text-align:center;
}
.FancyBorder-blue{
  border-color: #00f;
}
.Dialog-title{
  margin:0;
  font-family:sans-serif;

  /* text-align:center; */
}

複数の箇所に子要素を追加したいケース(一般的ではない)

  • や のような React の要素はただのオブジェクトなので、他のあらゆるデータと同様に props として渡すことができる
  • 他のライブラリでいうと、slot に似ている
  • propsに渡せるものに制限はない
function SplitPane(props){
  return(
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App(){
  return(
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

特化したコンポーネント (Specialization)

?何が特化なのかよくわからなかった

function Dialog(props){
  return(
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
       {props.title}
      </h1>
      <p className="Dialog-message">
       {props.message}
      </p>
    </FancyBorder>
  );
}

function WelcomeDialog(){
  return(
    <Dialog
      title="Welcome"
      message="Thank you for visiting our spacecraft!" />
  );
}
function Dialog(props){
  return(
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
      {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

class SignUpDialog extends React.Component{
  constructor(props){
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleSignUp = this.handleSignUp.bind(this);
    this.state = {login: ''};
  }

  render(){
    return(
    <Dialog title="Mars Exploration Program"
            message="How should we refer to you?">
      <input value={this.state.login}
        onChange={this.handleChange} />
      <button onClick={this.handleSignUp}>
        Sign Me Up!
      </button>
    </Dialog>
    );
  }

  handleChange(e){
    this.setState({login: e.target.value});
  }

  handleSignUp(){
    alert(`Welcome abroad, ${this.state.login}!`);
  }
}

継承は?

  • コンポーネント継承による階層構造が推奨されるケースは全く見つかっていない
    ?ここもよくわからなかった

  • コンポーネントはどのような props でも受け付けることができ、それはプリミティブ値でも、React 要素でも、あるいは関数であってもよい、ということに留意

  • コンポーネント間で非 UI 機能を再利用したい場合は、それを別の JavaScript モジュールに抽出することをお勧めする

5
2
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
5
2