質問: React初学者です。現在、入室管理アプリの作成を進めており、その選択肢の一つとしてViewにSPA要素を加えたく、Reactの学習をはじめました。Webに関してはHTML+css+jsの基本的なwebアプリの作成経験、MVCフレームワークではRailsを学び、タスク管理アプリなど基本的なアプリの作成経験がある程度です。動的Webに関してはあまり経験がありません。 React開発環境構築2018を参考にして環境を構築し、SPAの例を元に、単純なマテリアルUIを貼り付けることができるようになりました。 ここで、初歩的なことなのですが、Reactはサイトの例で出てくるようなRect.jsなどのコンポーネントと呼ばれるパーツのようなものを組み合わせてVIEW部分を作っていくために用いると理解しています。各コンポーネントの機能を実装するのがReactなのかなと理解しています。 ここでわからなくなったのが、デザインの構築の部分です。 ・**複数のコンポーネントを貼っていくときに、そのページとしての構成の構築はどこに記述して行うのがよいのか?** 例えばBootStrapならhtmlの記述に適応したいデザインを追加していくのでわかりやすかった。Reactではindex.jsxで最後ににApp.jsの仮装DOMを展開しているが、例えば ``` ``` のようにhtmlに大まかに構成を記入してそこにそれぞれの仮装DOMを展開するのがよいのか? そもそもApp.jsやindex.jsは何を記述するためのファイルを分割しているのか? ・**CSSやBootstrapは組み合わせてもいいのか?** 前述の通り、IDなどに対してCSSやBootstrapを適応してページのレイアウトを構成してもよいのか?例えばReactのコンポーネントの配置を考えるときに、Gridデザインなどを適応したい場合にはどのように記述するのがいいのか? ・**データの入出力について** データの入出力はどのタイミングで行えばよいのか?いくつか記事を調べたところ、MVCと異なり、FLUXの原則としてはAPIベースで問い合わせを行うこと、そして子コンポーネントではそのAPI呼び出しは行わないこと。というように理解しました。 REDUXについて つまりこれは「一番大元となり、他のコンポーネントを内部に持つ**親コンポーネント**を生成する際のコンストラクタ(?)でAPI(GET)を呼び出してJSONかなにかでデータを取得し、FORMやチェックリストは子コンポーネント内部のクリックアクションかなにかでDBなどのサーバサイドへAPI(PUT)呼び出しを行うようにしなさい」 ということでしょうか? 長文となり失礼いたします。サイトなどをいくつかみていたのですが、サイト間で書いてあることやコーディング方法に差分があり、サンプルプログラムもHello Worldやマテリアルを少し動かす程度で終わっているものが多かったため、先に進めず困ってしまっため質問いたしました。アドバイスをお願いいたします。
回答: > > ・複数のコンポーネントを貼っていくときに、そのページとしての構成の構築はどこに記述して行うのがよいのか? > > > 以下はreact-routerを使ったルーティングの例ですが、ページ単位のコンポーネントを用意する感じになると思います。 ``` // ルーティングの設定 const App = () => ( ); // トップページ const Home = () => ( <> Home > ); // Aboutページ const About = () => ( <> About > ); ``` コンポーネントを配置するディレクトリ構成は基本的に自由ですが、`Pages/{PageName}.js`などの様に、ページごとのコンポーネントをまとめる方法もあると思います。 `index.js`や`App.js`は、アプリケーションの要件にもよりますが、Reactで構築したDOMを流し込む、エントリポイントが記述されていることが多いと思います。 > > CSSやBootstrapは組み合わせてもいいのか? > > > react-bootstrap等のライブラリがありますので、それを使えばbootstrapを使うことができます。 ただ、Material-UIをご利用であれば不要ではないかと思います。 CSSはstyled-componentやCSS Modules, CSS in JSなどやり方は色々あります。 自分の記事で恐縮ですが、CSS Modulesの例を共有します。 https://qiita.com/nouka/items/89bdb81a49f556a7f629 > > データの入出力について > > > react-reduxを使う場合は、コンテナコンポーネントとプレゼンテーショナルコンポーネントの2つに役割を分担する方法が公式に書いてあります。 コンテナコンポーネント...データやコールバック関数をプレゼンテーショナルコンポーネントに渡す。 プレゼンテーショナルコンポーネント...DOMを構築する。コールバック関数を使ってデータを更新する。 親コンポーネントを用いてデータを子コンポーネントに渡すという部分は認識が合っていると思います。 全ての状態が1つの親コンポーネントで表現できればそれでも問題ないと思いますが、おそらくいくつかの単位に分けたくなると思いますので、ご参考いただければと思います。 追記: API呼び出しをどこに書くのか redux-thunkを使ったパターンを紹介します。 ``` export default function reducer(state, action) { switch (action.type) { case REQUEST_LOGIN: return Object.assign({}, state, { isFetching: true, }); case RESPONSE_LOGIN: return Object.assign({}, state, { isFetching: false, isLogin: action.isLogin, }); default: return state; } } export function requestLogin() { return { type: REQUEST_LOGIN, }; } export function responseLogin(json) { return { type: RESPONSE_LOGIN, isLogin: json.is_login, }; } // この関数がコンポーネントから呼ばれる // fetchの結果、非同期でActionがコールされ、Storeが書き換わります。 export function isLogin() { return (dispatch) => { dispatch(requestLogin()); return fetch('/api/auth', { credentials: 'include', cache: 'no-store' }) .then(response => response.json()) .then(json => dispatch(responseLogin(json))); }; } ``` reactは自由度が高いライブラリですので、色々なサイトを見てもそれぞれ違った方法で構築されている事が多いので、戸惑うことがあると思いますが、それがReactの良さでもあるのかもしれませんね。 回答になりましたでしょうか? 追加のご質問があれば、コメントいただければと思います。