--- title: React入門 tags: 読書感想文, 考察 --- * title React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで * 出版社 翔泳社 * 著者 --- repository * todo app https://github.com/sakakendo/todo-app * yahoo-shopping-ranking https://github.com/sakakendo/yahoo-shopping-ranking --- 1. React・Reduxとは Reactとは Virtual DOM,JSXが特徴としてあげられる。 Fluxとは フロントサイドでのユーザーの状態の管理などにjQueryの時代ではチェックボックス自体の状態を見る必要があったが、そこでjsonにデータを保管するようになったが複雑化に寄って副作用起きる可能性が出てきた。そこでFluxというデータを一方方向にながす設計思想がうまれた。これによってデータの不整合が起きづらい仕組みになった。 ちなみに[Redux](https://github.com/reduxjs/redux)はFluxの実装の一つであり、Facebook社の[Flux](https://github.com/facebook/flux)といった他のframeworkも存在する。 個人的には一番中核にStoreがあり、それを取り囲みdispatchされたアクションの管理をし、結果の適用をするReducerがあるイメージ。 View React Component Action 変化の型と、引数のデータを持っている Dispatcher 発生したActionをStoreに対して適用する State 状態をつかさどるデータ、ただのjson Store stateを保持し、dispatchされたactionをstateに適用して更新するロジックを司っている。 2. create-react-appで開発を始めよう 3. JSX Babel JSXやCoffeeScriptなどをブラウザで実行可能なJavaScriptにトランスパイルする webpack ソースファイルを一つのファイルとしてバンドルする。またLoaderという仕組みを使うことで画像やcssなどもjavascriptから扱えるようにしている。 ちなみに実際のwebpackでcssを読み込んだときの手順や仕組みに関しては以下が詳しかった。 [最新版で学ぶwebpack 4入門スタイルシート(CSSやSass)を取り込む方法](https://ics.media/entry/17376/) 4. Reactコンポーネント props ``` function SomeComponent(props){ return (<div>{props.name}</div>) } <SomeComponent name="坂本龍馬"/> /*こんな感じでプロパティを渡すことができる。*/ function SomeComponent(props){ return (<div>{props.children}</div>) } <SomeComponent>坂本龍馬</SomeComponent> /* こんな感じで文字列やReact.Componentなどを渡すことができる*/ ``` propTypes プロパティの値にバリデーションをかけることができる。 ``` import propTypes from 'prop-types'; SomeComponent.propTypes={ /* プロパティの型を指定する */ name:propTypes.string /* こんな感じでpropsの方が指定できる。*/ complexObject:propTypes.shape({ /* こんな感じでオブジェクトの中の個別のプロパティを指定できる*/ name:propTypes.string, age:propTypes.number }) someElement:propTypes.element, /*React Element*/ someNode:propTypes.node, /*小要素になりうる*/ helloElement:propTypes.instanceOf(Hello),/* 特定のReactエレメント(もしくはオブジェクト?)であることを指定できる。 */ /* 値を指定する oneOf,oneOfType,any */ /* propsが必要であることを示す isRequired */ /* デフォルト値 */ Hello.defaultProps={ name:'坂本龍馬' } } ``` https://github.com/airbnb/prop-types * 気になったところ propTypesには値の範囲を指定するなど他にも機能がありそう。 実際の評価はいつ行われてる? TodoAppをつくる。まだデータをreduxで管理していないので、setStateでデータを更新する。 基本的にはviewのイベントからjsの関数が呼ばれ、その中でsetStateを使ってstateを更新するイメージ。formの場合は`<input type="text" onChange={this.handleChange}/>`で入力値の変化を監視、`handleChange(e){this.setState({inputValue:e.target.value});}`でstateの更新、`<input type="button" onClick={this.handleSubmit}/>`でボタンが押されたのを関知したらそれに応じた処理を実行する。 ``` /* App.js, TodoInput.jsの関係 */ ``` stateを宣言する。 呼び出されるかわであるaddTodoにはstateなどがないのでbindする必要がある。 App.js ``` // constructor内でbindする方法 constructor(props){ this.addTodo=this.addTodo.bind(this) } // arrow関数でこの場で関数として定義し直すことで渡してる? <TodoInput addTodo={(title)=>{this.addTodo(title)}}/> //property initializer syntaxを使う //この方法を使うと最初からbindされたメソッドを作ることができるらしい。 //html(jsx?)内部からjsの関数を読んだときの特性?よくわからないからまた今度調べる // https://babeljs.io/docs/en/babel-plugin-proposal-class-properties // https://qiita.com/takaken/items/8375247778a51f5a42ff //addTodo(title){ addTodo=(title)=>{ ``` 5. Reduxでアプリケーションの状態を管理しよう ``` // state const initialState={ } // reducer function taskReducer(state=initialState,action){ switch(action_type){ case 'ADD_TASK': return { ...state, tasks: state.tasks.concat([action.task]) } defaul: return state; } } // storeの生成 const store=createStore(taskReducer); /* dispatch,subscribe,getState,replaceReducerをメソッドに持つオブジェクト */ // actionCreater // 現在のtaskの状態を受け取り、taskに準じたオブジェクトをpayloadに乗せて返す関数 const addTask=(task)=>{ type: 'ADD_TASK', payload:{ task } } // actionの発行 store.dispatch(addTask('first task')); // 複数のstore,reducerの合成 combineReducer(reducers) // e.g // combineReducers({ todos: myTodosReducer, counter: myCounterReducer }) // https://redux.js.org/api/combinereducers ``` react-reduxに関して ファイル構成が深くなり複雑になったときにStoreの値などを親のコンポーネントからバケツリレーしないですむようにstateの値をやactionをstoreがない状態でも呼び出せるようにpropsに紐づけたりしている? ``` <Provider> connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options]) mapStateToProps(state,[ownProps]) // このownPropsは触らなかった場合はそのまま渡されて、stateと合成したい場合などのときに受け取ればいい? mapDispatchToProps(dispatch,[ownProps]) connectAdvanced(selectorFactory,[connectOptions]) ``` 6. ルーティングを実装しよう client sideでルーティングをすることでstateを保持しておくことができる。しかし、この場合、遷移の履歴をどう残すかが鍵になる。 URL hashを用いる。 url hashの値が変わったときにhachchangeが発火するのでそれによってイベントをハンドリングして対応しているコンポーネントを呼び出す方法 history APIを用いる URLに対応しているコンポーネントを呼び出す、ページ内の遷移時にはコンポーネントを呼び出し、実際にはHTTP Requestは発行せずhistory APIを通して履歴をpushすることで履歴を追加する。ただし直接URLを入力した場合にはサーバー上にリクエストが発行されてしまうので404エラーを返してします。実際にはリソースがない場合には起点となるページを返す必要がある。 * react-router v4 `Link,Redirect`を使用することでURLの変更をすることができたがreactのコードから変更することはできない。 * react-router-redux `push`,`replace` と行った関数を通じてreduxで管理されているhistoryを更新しURLの変更をすることができる。しかしreact-router 2.x,3.xのみにしか対応していない? https://github.com/reactjs/react-router-redux > This repo is for react-router-redux 4.x, which is only compatible with react-router 2.x and 3.x * connected-react-router 最終的にこれを使った https://github.com/supasate/connected-react-router 7. Redux Middleware 未 8. Reduxの非同期処理 未 9. UIをきれいにしよう [material-ui](https://material-ui.com/)の使い方、こんな感じでimportしてReactコンポーネントとして扱えるみたい ``` import Button from 'material-ui/Button'; return(<Button raised color="primary" onClick={()=>addTask(task)}>add</Button>) ``` animation react-addons-css-transition-groupを使っているみたい。まだ試していない。 https://ja.reactjs.org/docs/animation.html ``` <ReactCssTransitionGroup transitionName="example" transitionEnterTimeout={300}><h1>hello world</h1></ReactCssTransitionGroup> ``` ``` .example-enter{ opacity:0; transform: translateX(100px); } .example-enter.example-enter-active{ opacity: 1; transform: translateX(0); tramsition: 300ms easy-in; } ``` 10. より実践的なアプリケーションを作ろう yahoo-shopping-rankingを表示するアプリケーションを作った。非同期処理とページルーティングの練習。 11. アプリケーションのテストをかこう まだ Jest https://jestjs.io/ja/ redux-mock-store https://github.com/dmitry-zaets/redux-mock-store jest-fetch-mock https://www.npmjs.com/package/jest-fetch-mock http://www.wheresrhys.co.uk/fetch-mock/#usageusage-with-jest enzyme https://github.com/airbnb/enzyme 12. 作ったアプリケーションを公開しよう github pagesもしくはfirebase ``` // cli toolのインストール、ログイン npm i -g firebase-tools firebase --version firebase login // 実際にプロジェクトをデプロイするときの手順 firebase init npm run build firebase deploy ``` 13. サーバーサイドレンダリング まだ React v16以降 `ReactDOMServer.renderToNodeStream`,`ReactDOM.hydrate` ``` app.get('/',(req,res)=>{ const stream=ReactDomServer.renderToNodeStream( <HTML><App/></HTML> ); stream.pipe(res); }); ``` --- 総括・感想 このあとなにしよう。 認証あたりがさっぱりわからない。 UIの勉強したい。 気になったところ