react+reduxで作成しているソースファイルの肥大化をなんとかしたい
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 2,080
前提・実現したいこと
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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
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を持つことを防ぐものでした。かといってトップから全て渡していく必要があるというものでもありません。コンポーネント単位で必要な情報だけ取得していくと再利用性が高い物ができるかと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.32%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/02/27 11:34
いただいた回答のおかげで無事解決いたしました。
今回、メインとなるMainPを作り、その下にHeaderC、ContentsC、FooterCを作り、その下に、それぞれPをぶら下げました。
また、一つだったstateを3つのファイルに分け、react-rudexのmapStateToPropsで取得することで良い感じで分割できました。
ありがとうございます