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
と同じです。
HTML
1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset="utf-8">
5 <meta name="viewport" content="width=device-width">
6 <title>React Redux Sample</title>
7</head>
8<body>
9 <div id="main"></div>
10 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
11 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script>
12 <script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
13 <script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.2/react-redux.min.js"></script>
14 <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.23.1/babel.min.js"></script>
15 <script type="text/babel">
16const InputTextP = () => (
17 <textarea name="text">
18 </textarea>
19);
20const SubmitButtonP = () => (
21 <button type="submit">
22 出力
23 </button>
24);
25const InputP = ({onSubmit}) => (
26 <form onSubmit={onSubmit}>
27 <InputTextP />
28 <br />
29 <SubmitButtonP />
30 </form>
31);
32const InputC = ReactRedux.connect(
33 (state, ownProps) => ({}),
34 (dispatch, ownProps) => ({
35 onSubmit: (e) => {
36 e.preventDefault();
37 dispatch(submit(e.currentTarget.text.value));
38 }
39 }),
40)(InputP);
41const MessageP = ({text}) => (
42 <pre>
43 {text}
44 </pre>
45);
46const OutputC = ReactRedux.connect(
47 (state, ownProps) => ({
48 text: state.text
49 })
50)(MessageP);
51const MainP = () => (
52 <div>
53 <InputC />
54 <OutputC />
55 </div>
56);
57
58const SUBMIT = 'SUBMIT';
59const submit = (text) => ({
60 type: SUBMIT,
61 payload: {text}
62});
63const initialState = {
64 text: ''
65};
66const reducer = (state = initialState, action) => {
67 switch (action.type) {
68 case SUBMIT:
69 return Object.assign({}, state, {
70 text: action.payload.text
71 })
72 default:
73 return state
74 }
75};
76const store = Redux.createStore(reducer)
77
78ReactDOM.render(
79 <ReactRedux.Provider store={store}>
80 <MainP />
81 </ReactRedux.Provider>,
82 document.getElementById('main')
83);
84 </script>
85</body>
86</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 02:34