質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • JavaScript

    19927questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • React.js

    1078questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

react+reduxで作成しているソースファイルの肥大化をなんとかしたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,201

kujira13

score 1

前提・実現したいこと

react+reduxで開発しているclassの肥大化をなんとかしたい

発生している問題・エラーメッセージ

es6(babel)+react+reduxの環境で開発を実施しています。
現在の方針はトップのコンテナーのclassに全ての処理を実装し、それを実際に使用する子コンポーネントまでバケツリレーすることで処理を実施しています、
作業が進むにつれ、classの肥大化が目立ってきました。
肥大化を防ぐ良い案はないでしょうか。

該当のソースコード

```javascript
import React from 'react';

import Header from './Header';
import Main from './Main';
import Footer from './Footer';

class AdminContainer extends React.Component {
constructor(props) {
super(props);

this.method1 = this.method1.bind(this);
this.method2 = this.method2.bind(this);
this.method3 = this.method3.bind(this);
}

/* 下位に渡すmethodが増え、ファイルがどんどん大きくなる */
method1(){ ...省略... } 
method2(){ ...省略... }
method3(){ ...省略... }

render() {
<div>
<Header />
<Main 
Method1={this.Method1()}
Method2={this.Method2()}
Method3={this.Method2()}
/> 
<Footer />
</div>
);
}
}

試したこと

classに対し、別ファイルにてprototypeによる実装を行いましたが、うまくいかず・・・
何か他にいい案ありましたら、お願いいたします。

import AdminContainer from './AdminContainer';

AdminContaner.prototype.method4 = () => {
...省略...
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

Reduxも使っているのであれば、react-reduxも使ってみてください。そしてUsage with Reactで書き方を学んでみてください。それだけで、肥大化は防げるはずです。

以下、Reduxの公式マニュアルが推奨している方法です(たぶん)。かといって、必ずこうしろと言うわけではありません。

始めに、コンポーネントを二つの種類に分けます。

  • 表現部品 Presentational Components
    どのような見た目にするのかを書くコンポーネントです。divやspanとかではない意味のあるHTMLのタグが実際に使われるのもこのコンポーネントです。
  • 容器部品 Container Components
    どのように動くのかを書くコンポーネントです。いわゆる振る舞いやロジックをここに書きます。

renderするときは、これが入れ子のように作ります。サンプルを作ったので見てましょう。わかりやすいようにPresentational Componentsは終わりにPを、Container Componentsは終わりにCを付けた名前にしています(そういう命名規則にすべきとかはありません)。
※ HTMLで1ファイルになるようにしていますが、実際は分割して作ることになるでしょう。
※ Presentational Componentsは状態を持たないため、stateless functional componentsとして作成できます。つまり、一つの関数としてくれると言うことで、これはrender()しかないReact.Componentと同じです。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>React Redux Sample</title>
</head>
<body>
  <div id="main"></div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.2/react-redux.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.23.1/babel.min.js"></script>
  <script type="text/babel">
const InputTextP = () => (
  <textarea name="text">
  </textarea>
);
const SubmitButtonP = () => (
  <button type="submit">
    出力
  </button>
);
const InputP = ({onSubmit}) => (
  <form onSubmit={onSubmit}>
    <InputTextP />
    <br />
    <SubmitButtonP />
  </form>
);
const InputC = ReactRedux.connect(
  (state, ownProps) => ({}),
  (dispatch, ownProps) => ({
    onSubmit: (e) => {
      e.preventDefault();
      dispatch(submit(e.currentTarget.text.value));
    }
  }),
)(InputP);
const MessageP = ({text}) => (
  <pre>
    {text}
  </pre>
);
const OutputC = ReactRedux.connect(
  (state, ownProps) => ({
    text: state.text
  })
)(MessageP);
const MainP = () => (
  <div>
    <InputC />
    <OutputC />
  </div>
);

const SUBMIT = 'SUBMIT';
const submit = (text) => ({
  type: SUBMIT,
  payload: {text}
});
const initialState = {
  text: ''
};
const reducer = (state = initialState, action) => {
  switch (action.type) {
    case SUBMIT:
      return Object.assign({}, state, {
        text: action.payload.text
      })
    default:
      return state
  }
};
const store = Redux.createStore(reducer)

ReactDOM.render(
  <ReactRedux.Provider store={store}>
    <MainP />
  </ReactRedux.Provider>,
  document.getElementById('main')
);
  </script>
</body>
</html>

階層構造は下記のようになっています。

MainP <div>
├InputC
│└InputP <form>
│ ├InputTextP <textarea>
│ └SubmitButtonP <button>
└OutputC
 └MessageP <pre>

さらにPresentational Componentsの中にContainer Componentsを入れてもかまいません。react-reduxが提供するProviderにstoreを渡すことで、自動的にコンポーネントでは同じstoreを受け取って、それに対するstateやdispatchが使えるようになっています。

Container Componentsで振る舞いを全て書くことになるため、ここが肥大化しそうと思うかも知れませんが、細かくコンポーネントに分割していけば、わかれて記載可能です。また、モジュールベースで作っていれば、別のページや場所での再利用も簡単にできるでしょう。

さわりだけですが、なんとなく掴めたでしょうか?ReduxはFluxの一種(厳密に違うが)であり、各コンポーネントでstateを持つことを防ぐものでした。かといってトップから全て渡していく必要があるというものでもありません。コンポーネント単位で必要な情報だけ取得していくと再利用性が高い物ができるかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/27 11:34

    意味が理解できるまで時間がかかってしまい、結果お礼が遅くなってしまい申し訳ありません。
    いただいた回答のおかげで無事解決いたしました。
    今回、メインとなるMainPを作り、その下にHeaderC、ContentsC、FooterCを作り、その下に、それぞれPをぶら下げました。
    また、一つだったstateを3つのファイルに分け、react-rudexのmapStateToPropsで取得することで良い感じで分割できました。
    ありがとうございます

    キャンセル

同じタグがついた質問を見る

  • JavaScript

    19927questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • React.js

    1078questions

    Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。