ReactずReduxを䜿甚した同圢アプリケヌション

ですから、あなたはTodoリストが倧奜きであるこず、぀たりTodoリストを曞くこずが本圓に奜きであるこずを知っおいるので、新しく、おいしい、栄逊䟡の高い「栄逊䟡の高い」Per。 Fluxフレヌムワヌクを䜿甚しおリストを䜜成しおください、 Redux  私はあなたに最高のこずを願っおいたす。

この蚘事では、独自のReduxアプリケヌションをビルドする方法を孊びたす。



これがあなたがこの人生で望むもののように芋えるなら、カットの䞋に進んでください、そうでないなら、気にしないでください。

お䌝えしたいのですが...これは非垞に小さなチュヌトリアルではありたせんので、手を䌞ばしお厄介な道の準備をしおください。腕や脚を突き出さないでください...

停止しお、埅っお、Reduxずは䜕ですか


ああ、私はあなたが尋ねおうれしいです

ReduxはDanil Abramovの新しいFluxフレヌムワヌクで、倚くの䞍必芁な困難を取り陀きたす。 ここでこのフレヌムワヌクが䜜成された理由を読むか、䞀般的にTLを参照しおください DR Reduxはアプリケヌションの状態を1か所に保持し、この状態ず察話するための最小限でありながら非垞に匷力な方法を定矩したす状態orig。 。

埓来の Flux フレヌムワヌクに粟通しおいる堎合、最倧の違いは、Vaults Stores orig。の䞍足ず、Reducer Reducers orig。の存圚です。
Reduxでは、アプリケヌションの状態党䜓が別々のリポゞトリに分割されるのではなく、1぀の堎所Reduxのむンスタンスに存圚したすこれは少し同型に抵抗できたす。
「Reducer」は、状態がどのように倉化するかの説明であり、本質的には䜕も倉化せず、次のようになりたす。
function exampleReducer(state, action) { return state.changedBasedOn(action) } 

どうやっお 少し埌で芋るでしょう。

Reduxはフレヌムワヌクずいうよりも゜リュヌションのようなものだず思うでしょう。 これは、すべおの最高のFluxアむデアを含む最小ベヌスです。 この蚘事は、あなたがそれをうたく䜿い、繁栄し、最小限の突然倉異で進むこずをあなたに教えるこずを願っおいたす。

自分を快適にする


WebpackずBabelを䜿甚しおアプリケヌションをバンドルしたす。なぜなら、私たちはクヌルで、スマヌトで、楜しく、そしおコヌドをその堎でリロヌドしお最新のES6 / 7チップを提䟛できるからです。

たず、ディレクトリを䜜成し、そこにいく぀かのファむルを配眮する必芁がありたす。

事前に準備したpackage.jsonは次のずおりです。
package.json
 { "name": "isomorphic-redux", "version": "1.0.0", "description": "Basic isomorphic redux application", "main": "index.js", "scripts": { "start": "NODE_PATH=$NODE_PATH:./shared node .", "dev": "npm run start & webpack-dev-server --progress --color" }, "author": "<your-name> <<your-email>>", "license": "MIT", "dependencies": { "axios": "^0.5.4", "express": "^4.13.2", "immutable": "^3.7.4", "object-assign": "^3.0.0", "react": "^0.13.3", "react-redux": "^0.2.2", "react-router": "^1.0.0-beta3", "redux": "^1.0.0-rc" }, "devDependencies": { "babel": "^5.8.20", "babel-eslint": "^4.0.5", "babel-loader": "^5.3.2", "eslint": "^1.0.0", "eslint-plugin-react": "^3.1.0", "react-hot-loader": "^1.2.8", "webpack": "^1.10.5", "webpack-dev-server": "^1.10.1" } } 


同様に
webpack.config.js
 var path = require('path'); var webpack = require('webpack'); module.exports = { entry: [ 'webpack-dev-server/client?http://localhost:8080/', 'webpack/hot/only-dev-server', './client' ], output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js' }, resolve: { modulesDirectories: ['node_modules', 'shared'], extensions: ['', '.js', '.jsx'] }, module: { loaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loaders: ['react-hot', 'babel'] } ] }, plugins: [ new webpack.HotModuleReplacementPlugin(), new webpack.NoErrorsPlugin() ], devtool: 'inline-source-map', devServer: { hot: true, proxy: { '*': 'http://localhost:' + (process.env.PORT || 3000) } } }; 


および.babelrc 「ES7」シュガヌ甚
 { "optional": ["es7.decorators", "es7.classProperties", "es7.objectRestSpread"] } 

率盎に蚀っお、これらのファむルはそれほど泚目に倀するものではなく、合理的な開発環境を䜜成しただけです。
OK、 npm iを実行しおすべおの䟝存モゞュヌルをダりンロヌドする必芁があり、開始できたす。

シヌモアをください


アプリケヌションの基本構造は次のようになりたす。
 client/ shared/ index.js server.jsx 

コヌドの䞻芁郚分はすべおsharedディレクトリにありたすが、クラむアント郚分ずサヌバヌ郚分を分離するには、いく぀かの接着コヌドが必芁です。

index.js
 'use strict'; require('babel/register')({}); var server = require('./server'); const PORT = process.env.PORT || 3000; server.listen(PORT, function () { console.log('Server listening on', PORT); }); 


server.jsxを実行するファむルだけなので、ES6 / JSXを䜿甚できたす。

サヌバヌの機胜はExpressによっお実行されたす。これは、サヌバヌがより単玔であり、既に知っおいる可胜性があるためです。
server.jsx
 import express from 'express'; const app = express(); app.use((req, res) => { const HTML = ` <DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Isomorphic Redux Demo</title> </head> <body> <div id="react-view"></div> <script type="application/javascript" src="/bundle.js"></script> </body> </html> `; res.end(HTML); }); export default app; 


かなり暙準的なでたらめ。 グロヌバルミドルりェアでExpressサヌバヌをセットアップしたすが、䜕も凊理せず、存圚の空癜を調べるのに圹立぀空のWebペヌゞのみを凊理したす。 それを修正したしょう。

に぀いおのルヌチン


おそらく、゚クスプレスルヌティングずテンプレヌトを䜿甚するこずは簡単だず思いたす。 残念ながら、サヌバヌずクラむアント間でできるだけ倚くのロゞックを共有したいので、あなたは間違っおいたす。 クラむアントずサヌバヌでルヌティングできるため、 React Routerを䜿甚したす。

そのため、React Routerが埋め蟌たれるルヌトコンポヌネントshared/components/index.jsxがありたす。 このようにしお、アプリケヌション党䜓キャップ​​や地䞋宀などに矎孊を远加するこずができたす。玠晎らしいSPAに適したアヌキテクチャです。
共有/コンポヌネント/index.jsx
 import React from 'react'; export default class AppView extends React.Component { render() { return ( <div id="app-view"> <h1>Todos</h1> <hr /> {this.props.children} </div> ); } } 


ここの子はコンポヌネントツリヌに倉わり、䟝存関係を持぀魔法の埌にルヌタヌが提䟛したす。 ここには特別なものはありたせん。すべおをそのたた印刷するだけです。

次に、ルヌトを定矩する必芁がありたす
shared / routes.jsx
 import React from 'react'; import { Route } from 'react-router'; import App from 'components'; export default ( <Route name="app" component={App} path="/"> </Route> ); 


ここでは、 '/'パスに沿っおcomponents/indexを衚瀺するようにReact Routerに指瀺したす。 いいですね
次に、サヌバヌで同じこずを行いたす。
server.jsx
 import React from 'react'; import { Router } from 'react-router'; import Location from 'react-router/lib/Location'; import routes from 'routes'; app.use((req, res) => { const location = new Location(req.path, req.query); Router.run(routes, location, (err, routeState) => { if (err) return console.error(err); const InitialComponent = ( <Router {...routeState} /> ); const componentHTML = React.renderToString(InitialComponent); const HTML = `...`; res.end(HTML); }); }); 


ここで、いく぀かの新しいおもちゃをむンポヌトし、衚珟する芁求を転送するようにルヌタヌに指瀺したす。 routeState倉数に戻り、芁求されたルヌトを衚瀺できるこずを願っおいたす。 次に、 Reactの smart renderToStringメ゜ッドを䜿甚しお、コンポヌネントをHTML文字列で出力したす。これは、前に䜜成したreact-view divでクラむアントに提䟛したす。

 <div id="react-view">${componentHTML}</div> 

npm startを実行npm start http// localhost3000 /ルヌトがHTMLに挿入されたこずがわかりたす。
トドスルヌト
いく぀かの゚ラヌがコン゜ヌルに衚瀺され、ルヌタヌに耇数の倀が必芁であるこずを瀺しおいたす。 これは、クラむアントがbundle.jsをダりンロヌドしようずしおいるためですが、ただwebpackの゚ントリポむントを蚭定しおいないため、これはそのようなゎミです。

芋た目は玠晎らしく、あなたの脳はすでに壊れおいるず思いたすが、今は静的なペヌゞがありたす。 Reactからすべおのゞュヌシヌなパルプを入手するには、クラむアントにルヌティングを実装する必芁がありたす。

だから、 client/index.jsxを開いお䜕かを曞いおください
クラむアント/ index.jsx
 import React from 'react'; import { Router } from 'react-router'; import { history } from 'react-router/lib/BrowserHistory'; import routes from 'routes'; React.render( <Router children={routes} history={history} />, document.getElementById('react-view') ); 



Routerコンポヌネントをreact-view divに挿入するようにReactに指瀺し、適切なパラメヌタヌを枡したした。 サヌバヌ郚分には衚瀺されなかった履歎オブゞェクト、React Router構成の必芁な郚分盎接衚瀺された堎合、およびURLの倖芳に぀いお説明したす。 そしお、私たちはきれいな斜蚭を求めおいたす したがっお、 BrowserHistoryでHTML5 History APIを䜿甚したすが、叀いブラりザヌではHashHistoryを䜿甚しお、アドレスから/# URLを取埗できたす。

これで、 npm run devアプリケヌションをnpm run devでき、Webpackがbundle.jsを凊理したす。 あたりおもしろそうではありたせんが、 http// localhost8080 /にアクセスするず、゚ラヌなく動䜜するはずです。 ルヌティングが完了し、Reduxアクションの準備ができたした。

削枛、再利甚、リデュヌス


ReduxはFluxに非垞によく䌌おいたすが、以前にストレヌゞの代わりにリデュヌサヌが䜿甚されるこずを述べたした。 最初に、Todoシヌトを倉曎する簡単な手順をいく぀か䜜成したす。
共有/アクション/ TodoActions.js
 export function createTodo(text) { return { type: 'CREATE_TODO', text, date: Date.now() } } export function editTodo(id, text) { return { type: 'EDIT_TODO', id, text, date: Date.now() }; } export function deleteTodo(id) { return { type: 'DELETE_TODO', id }; } 


ご芧のずおり、Reduxでは、 アクションクリ゚ヌタヌは、順番にフォヌマットされたオブゞェクトを返す単なる関数です。 魔法ではありたせん。それを凊理するために枛速機が必芁です。
共有/レデュヌサヌ/ TodoReducer.js
 import { List } from 'immutable'; const defaultState = new List(); export default function todoReducer(state = defaultState, action) { switch(action.type) { case 'CREATE_TODO': return state.concat(action.text); case 'EDIT_TODO': return state.set(action.id, action.text); case 'DELETE_TODO': return state.delete(action.id); default: return state; } } 


すべおが再び単玔です。 ここで、 Immutable Listオブゞェクトを䜿甚しお、䞍倉の状態をリポゞトリに栌玍しより倧きなアプリケヌションではより耇雑になる可胜性がありたす、アクションに応じお状態の新しいバヌゞョンを返すこずができたす。

Reduxはそれほど頑固ではなく、レデュヌサヌからの期埅は2぀だけです。
  1. 眲名(state, action) => newStateです。
  2. レデュヌサヌは枡された状態を倉曎したせんが、新しいバヌゞョンを返したす。


ご芧のずおり、埌者はImmuatable.jsに適しおいたす

ここでは単玔なスむッチ構造を䜿甚したすが、気に入らない堎合は、空癜を曞くこずをためらわないでください。

Reduxは単䞀のリデュヌサヌの䜿甚に限定されたせん。それらを取埗するために、reducer reducers/index.js䜜成できたす。
 export { default as todos } from './TodoReducer'; 

党員が持っおいるので、実際には必芁ありたせんが、将来必芁になりたす。

IIIiiii ...アクション


レデュヌサヌずアクションに぀いお話すのは良いこずですが、アプリはそれに぀いお䜕も知りたせん それを倉える時が来たした。

Reduxむンスタンスをコンポヌネントツリヌにプッシュしお、これらすべおを凊理し、これらすべおをリンクする必芁がありたす
NPMのreact-reduxは、これに圹立぀いく぀かのreact-redux 。

server.jsx
 import { createStore, combineReducers } from 'redux'; import { Provider } from 'react-redux'; import * as reducers from 'reducers'; app.use((req, res, next) => { const location = new Location(req.path, req.query); const reducer = combineReducers(reducers); const store = createStore(reducer); Router.run(routes, location, (err, routeState) => { if (err) return console.error(err); const InitialView = ( <Provider store={store}> {() => <Router {...routeState} /> } </Provider> ); 



リク゚ストごずにReduxストレヌゞコンポヌネントのむンスタンスを䜜成し、 Providerルヌトコンポヌネントをラップするこずにより、コンポヌネントツリヌ党䜓アクセスが必芁な堎合は<component> .context.reduxずしお利甚可胜に転送しProvider 。
クラむアントに初期状態を䞎えお、保管斜蚭を氎玠化できるようにする必芁もありたす。

Reduxの状態を尋ねるだけです
 const initialState = store.getState(); 


そしお、HTMLテンプレヌトに数行远加したす。
 <title>Redux Demo</title> <script type="application/javascript"> window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}; </script> 

その埌、 window.__INITIAL_STATE__介しおクラむアントの状態にアクセスできるようになりたす。
今やらなければならないこずは、すべおをImmutable.jsコレクションに倉換するこずです。 そしお、新しいリポゞトリをむンスタンス化するずきにそれらをReduxに枡したす。

クラむアント/ index.jsx
 import { createStore, combineReducers } from 'redux'; import { Provider } from 'react-redux'; import * as reducers from 'reducers'; import { fromJS } from 'immutable'; let initialState = window.__INITIAL_STATE__; // Transform into Immutable.js collections, // but leave top level keys untouched for Redux Object .keys(initialState) .forEach(key => { initialState[key] = fromJS(initialState[key]); }); const reducer = combineReducers(reducers); const store = createStore(reducer, initialState); React.render( <Provider store={store}> {() => <Router children={routes} history={history} /> } </Provider>, document.getElementById('react-view'); ); 


これは、サヌバヌから枡された状態でストレヌゞをハむドレむトするこずを陀いお、サヌバヌの状態を初期化するこずず同じです。

本圓にアプリケヌションの完成に近づいおいたす。すべおのポむントを接続するために、いく぀かのコンポヌネントが残っおいたす。

すべおのポむントを接続する


3぀のコンポヌネントを䜿甚しお、少し冗長な情報を衚瀺したすほずんどの堎合そうですが、これは「スマヌト」コンポヌネントず「ダム」コンポヌネントのReduxの違いを瀺したす。これは倧芏暡アプリケヌションで非垞に重芁です。

スマヌトコンポヌネントはReduxストレヌゞむベントをサブスクラむブしたずえば、 @ connectorデコレヌタ構文を䜿甚、プロパティを介しお他のコンポヌネントにツリヌをプッシュしたす。 ツリヌのどこにでも配眮できたすが、より耇雑なアプリケヌションを開発する堎合、通垞は最䞋局に到達したす。

ここでは1぀だけを䜿甚したす
共有/コンポヌネント/ Home.jsx
 import React from 'react'; import TodosView from 'components/TodosView'; import TodosForm from 'components/TodosForm'; import { bindActionCreators } from 'redux'; import * as TodoActions from 'actions/TodoActions'; import { connect } from 'react-redux'; @connect(state => ({ todos: state.todos })) export default class Home extends React.Component { render() { const { todos, dispatch } = this.props; return ( <div id="todo-list"> <TodosView todos={todos} {...bindActionCreators(TodoActions, dispatch)} /> <TodosForm {...bindActionCreators(TodoActions, dispatch)} /> </div> ); } } 



次に、2぀の「ダム」コンポヌネントを䜜成したすが、たず、ここで䜕が起こるかを芋おみたしょう。

デコレヌタに慣れおいない堎合 @connectorセクション、最善の方法は、これがコンポヌネントのmixinず同じであるず理解するこずです。 おそらく、Pythonなどの他の蚀語でも同様の構成䜓を芋たこずがあるでしょう。

そうでない堎合、javascriptでは、これらは䜕らかの方法で他の関数ここでは「クラス」を倉曎する単なる関数です。

@connectデコレヌタは、別のコンポヌネント <Connector> でクラスをラップし、コンポヌネントのプロパティずしお状態の芁求された郚分にアクセスできるため、 todosを䜿甚できたす。 たた、Reduxからdispatch関数ぞのアクセスを提䟛したす。これにより、次のようにアクションを凊理できたす。
 dispatch(actionCreator()); 

最埌に、ReduxのbindActionCreators関数を䜿甚しお、関連するアクションクリ゚ヌタヌを転送したす。
぀たり、子コンポヌネントでは、アクション䜜成者をdispatch()関数でラップするこずなく盎接呌び出すこずができたす。

芋お
コンポヌネント/ TodosView.jsx
 import React from 'react'; export default class TodosView extends React.Component { handleDelete = (e) => { const id = Number(e.target.dataset.id); // Equivalent to `dispatch(deleteTodo())` this.props.deleteTodo(id); } handleEdit = (e) => { const id = Number(e.target.dataset.id); const val = this.props.todos.get(id).text // For cutting edge UX let newVal = window.prompt('', val); this.props.editTodo(id, newVal); } render() { return ( <div id="todo-list"> { this.props.todos.map( (todo, index) => { return ( <div key={index}> <span>{todo}</span> <button data-id={index} onClick={this.handleDelete}> X </button> <button data-id={index} onClick={this.handleEdit}> Edit </button> </div> ); }) } </div> ); } } 


ここでは、アクション䜜成者に関連付けられおいる削陀ボタンず倉曎ボタンの隣に、リポゞトリ内の各todo芁玠を衚瀺したす。

たた、クラスの定矩では「矢印」関数を䜿甚したす。そのコンテキストはクラスのコンストラクタヌに関連付けられおいたすこれらの関数ぱグれキュヌタヌからコンテキストを継承するため。 ES6クラスの通垞の関数レンダヌなどを䜿甚する堎合は、それらをコンテキストに関連付ける必芁がありたす。

React.createClassを䜿甚しお問題を回避し、ミックスむンを䜿甚するこずもできたすが、クリヌンさず䞀貫性のためにES6クラスを䜿甚するこずを奜みたす。


最埌に、定矩したす
コンポヌネント/ TodosForm.jsx
 import React from 'react'; export default class TodosForm extends React.Component { handleSubmit = () => { let node = this.refs['todo-input'].getDOMNode(); this.props.createTodo(node.value); node.value = ''; } render() { return ( <div id="todo-form"> <input type="text" placeholder="type todo" ref="todo-input" /> <input type="submit" value="OK!" onClick={this.handleSubmit} /> </div> ); } } 


これは、リポゞトリにtodoを远加するだけの「ダム」コンポヌネントでもありたす。

次に、ルヌトを決定する必芁がありたす

shared / routes.jsx
 import Home from 'components/Home'; export default ( <Route name="app" component={App} path="/"> <Route component={Home} path="home" /> </Route> ); 



Todoアプリ

そしお、 http// localhost8080 / homeに移動しお、動䜜䞭のアプリケヌションを芋おください

最埌のフロンティア非同期アクション


私はあなたが考えおいるこずを知っおいたす。

これは䞍可胜です。

そしお、私はそれが可胜であるず蚀いたす

Reduxのもう1぀の優れた機胜は、ディスパッチャからミドルりェアを刀別するこずです。これにより、アクションを非同期で倉曎できたす。 Reduxスレッドから、特定のシグネチャを持぀関数で機胜するこずに気づいたず思いたす。

Reduxミドルりェアを䜿甚しお、アプリケヌションでのアクションを簡単にし、アクションクリ゚ヌタヌを同期させたす。これにより、矎しくお玠晎らしいES6の玄束を䜿甚できるようになりたす。
共有/ lib / promiseMiddleware.js
 export default function promiseMiddleware() { return next => action => { const { promise, type, ...rest } = action; if (!promise) return next(action); const SUCCESS = type; const REQUEST = type + '_REQUEST'; const FAILURE = type + '_FAILURE'; next({ ...rest, type: REQUEST }); return promise .then(res = > { next({ ...rest, res, type: SUCCESS }); return true; }) .catch(error => { next({ ...rest, error, type: FAILURE }); // Another benefit is being able to log all failures here console.log(error); return false; }); }; } 


぀たり、アクションの「玄束」キヌを定矩するだけで、自動的に解決枈みたたは拒吊枈みの状態になりたす。
状態の倉化を远跡する必芁がある堎合は、オプションで自動生成された<TYPE> _REQUESTおよび<TYPE> _FAILUREのレデュヌサヌを远跡するこずもできたす。

そしお、それらを䜿甚するには、 client / index.jsxおよびserver.jsxの数行を倉曎する必芁がありたす

 ... import { applyMiddleware } from 'redux'; import promiseMiddleware from 'lib/promiseMiddleware'; ... const store = applyMiddleware(promiseMiddleware)(createStore)(reducer); 


たた、 リデュヌサヌずずもにinitialStateを転送するこずを忘れないでください

そしお今、私たちはアクション䜜成者のためにcreateTodoマゞックアクションを曞くこずができたす。䟋えば

 import request from 'axios'; const BACKEND_URL = 'https://webtask.it.auth0.com/api/run/wt-milomord-gmail_com-0/redux-tutorial-backend?webtask_no_cache=1'; export function createTodo(text) { return { type: 'CREATE_TODO', promise: request.post(BACKEND_URL, { text }) } } 


枛速機にわずかな倉曎を加えた埌。
 return state.concat(action.res.data.text); 


非同期アクションを䜿甚するTodoアプリ

これで、Todoが倖郚デヌタベヌスに保存されたした。 アプリケヌションの開始時にそれらをロヌドする堎合は、アクションのgetTodos䜜成者を远加するだけです。

 export function getTodos() { return { type: 'GET_TODOS', promise: request.get(BACKEND_URL) } } 


枛速機で圌を捕たえたす
 case 'GET_TODOS': return state.concat(action.res.data); 


そしお、 TodosViewが初期化されたずきに呌び出すこずができたす
 componentDidMount() { this.props.getTodos(); } 


ミドルりェアが初期リク゚ストたたは倱敗の可胜性に察しおアクションを呌び出す堎合、これらすべおをリデュヌサヌでキャッチし、それぞれブヌト時たたぱラヌ時にアプリケヌションの状態を曎新する方法を確認できたす。

埅っお...そしお、我々は状態の氎分補絊を砎らなかったのですか


はい それを修正したしょう

問題は、非同期アクションを远加したが、状態がクラむアントに送信される前に非同期アクションが完了するのを埅たないこずです。 クラむアントにロヌド画面を衚瀺できるので、それは重芁ではないず思うかもしれたせん。 サヌバヌにぶら䞋がるよりはたしですか

たあ、それは倚くの芁因に䟝存したす。 サヌバヌレンダリングの䞻な利点は、バック゚ンド同じデヌタセンタヌにある可胜性がありたすずの良奜な接続を保蚌できるこずです。 たずえば、ナヌザヌが倱われたモバむル接続を介しおサむトをダりンロヌドしようずする堎合、サヌバヌが自分のさたざたなリ゜ヌスから取埗するよりも、サヌバヌが初期状態を取埗するのを埅぀方がはるかに優れおいたす。

珟圚の状況でこの問題を解決するこずはそれほど難しくありたせん。 これはいく぀かの方法で行うこずができたすが、私がする道は理想からはほど遠いです

アクションクリ゚ヌタヌの配列ずしお、コンポヌネントに必芁なデヌタを決定したす。 クラス定矩で静的プロパティを䜿甚できたす。
 static needs = [ TodoActions.getTodos ] 


すべおのpromise呌び出しをキャッチし、デヌタを収集しお送信する関数も必芁です
shared / lib / fetchComponentData.js
 export default function fetchComponentData(dispatch, components, params) { const needs = components.reduce( (prev, current) => { return (current.needs || []) .concat((current.WrappedComponent ? current.WrappedComponent.needs : []) || []) .concat(prev); }, []); const promises = needs.map(need => dispatch(need(params))); return Promise.all(promises); } 


前述のスマヌトコンポヌネントはコネクタコンポヌネントにラップされるため、 WrappedComponentキヌも確認する必芁があるこずに泚意しおください。

次に、すべおのデヌタが揃ったずきにのみ応答するようにサヌバヌを構成したす。
 import fetchComponentData from 'lib/fetchComponentData'; Router.run(routes, location, (err, routeState) => { if (err) return console.error(err); function renderView() { // ... Rest of the old code goes here return HTML; } // Check this is rendering *something*, for safety if(routeState) fetchComponentData(store.dispatch, routeState.components, routeState.params) .then(renderView) .then(html => res.end(html)) .catch(err => res.end(err.message)); }); 


サヌバヌの非同期デヌタが完了するたで埅぀

呌び出しが繰り返されるのを避けるために、 onComponentMountからアクション䜜成者を削陀し、 npm run devを再起動しおサヌバヌ䞊の倉曎を曎新しおください。

䜕を孊びたしたか


なんお矎しい䞖界

さらに倚くのこずができたす。 倚数のルヌトがあるアプリケヌションでは、おそらくReact Router onLeaveハンドラヌを䜿甚しお、コンポヌネントが必芁ずするすべおのデヌタ ここなど をロヌドし、非同期APIで他のアクションをキャッチしたす。

これらすべおにもかかわらず、玠晎らしい機胜的な未来ぞの壮倧な探求を楜しんでいただければ幞いです。

Githubで最終結果を確認し、 ここで Reduxの詳现を読むこずもできたす。

Source: https://habr.com/ru/post/J264423/


All Articles