私は Isomorphic react
+react-router
アプリケーションを構築したいと思っており、数日間のグーグル検索の後、GET リクエストのみを処理する Isomorphic アプリケーションを実現できるようになりました。
これまでに行ったことは次のとおりです。
react-router
すべてのリクエストを処理するためにサーバーが使用されるreact-router
fetchData
ルートに一致する各 React View に存在する関数を呼び出します。- 先ほど取得したデータをReact Viewのpropsに設定し、レンダリングします。
string
string
以前に取得したデータをグローバル変数としてHTMLに挿入しwindow.__STATE__
、HTMLをクライアントに配信します。- サーバーからReact Appをレンダリングすることに成功しました
- クライアントがReactアプリのJavaScriptの読み込みを終えると、レンダリングを試みます。しかし、
window.__STATE__
Reactアプリのpropsから状態を渡すと、状態が同じなのでReactは再レンダリングしません。
問題は、POST/PUT/DELETE/その他リクエストでは動作しないことです。GETリクエストを処理するときは、およびreact-router
に関する情報が必要です。たとえば、ルート: があり、クライアントがこのURL: をリクエストした場合、次のようになります。また、次のようになります。params
query
/user/:uid
/user/1?foo=bar
params
{uid: 1}
query
{foo: 'bar'}
react-router
次に、それを関数に渡して、1 のfetchData
ユーザーを取得し、クエリで何らかの処理を実行することを認識できるようにします。uid
foo
POST リクエストでは、react-router
POST パラメータについてはわかりません。サーバーでは、もちろん POST パラメータをfetchData
関数に渡すことができますが、クライアントはどうでしょうか? クライアントは POST パラメータが何であるかを知りません。
サーバーがクライアントに POST パラメータを通知する方法はありますか? 以下は、ログイン ビューの例です。ユーザーがフォームを送信すると、サーバーはエラーの場合はエラー メッセージを表示し、成功した場合はダッシュボードにリダイレクトするようにします。
フェッチデータ.js
import whenKeys from 'when/keys';
export default (authToken, routerState) => {
var promises = routerState.routes.filter((match) => {
return match.handler.fetchData;
}).reduce((promises, match) => {
promises[match.name] = match.handler.fetchData(authToken, routerState.params, routerState.query);
return promises;
}, {});
return whenKeys.all(promises);
}
サーバー.js
...
app.use((req, res) => {
const router = Router.create({
routes,
location: req.originalUrl,
onError: next,
onAbort: (abortReason) => {
next(abortReason);
}
});
router.run((Handler, state) => {
fetchData(authToken, state).then((data) => {
// render matched react View and generate the HTML
// ...
})
});
});
...
ログイン.jsx
import React from 'react';
import DocumentTitle from 'react-document-title';
import api from './api';
export default class Login extends React.Component {
constructor(props) {
super(props);
// how to fill this state with POST parameters on error?
// how to redirect on success?
// and remember that this file will be called both from server and client
this.state = {
error: '',
username: '',
password: ''
};
}
// I saw some people use this function, but it'll only work if
// the form's method is GET
static willTransitionTo(transition, params, query) {
// if only we could read POST parameters here
// we could do something like this
transition.wait(
api.post('/doLogin', postParams).then((data) => {
transition.redirect(`/dashboard`);
});
);
}
render() {
return (
<DocumentTitle title="Login">
<div className="alert alert-danger">{this.state.error}</div>
<form method="post">
<input type="text" name="username" value={this.state.username} onChange={this._onFieldChange('username')} placeholder="Username" /><br />
<input type="password" name="password" value={this.state.password} onChange={this._onFieldChange('password')} placeholder="Password" /><br />
<button type="submit">Login</button>
</form>
</DocumentTitle>
);
}
_onFieldChange(name) {
var self = this;
return (e) => {
e.preventDefault();
var nextState = {};
nextState[name] = e.target.value;
self.setState(nextState);
}
}
}
ベストアンサー1
クライアントで「POST」データを取得する
クライアント側では、フォームが正常に送信された場合にサーバー上で受信した値に対応する方法でフォーム入力から値を抽出して POST データを取得します。
POSTデータの使用
これでPOSTデータは取得できましたが、React Router 0.13.x以前のバージョンではPOSTデータをトランジションフックに取り込む方法がまだありません。そこで、この機能のプルリクエストこれは、今後の v1.0 リリースの書き直しの一部として含まれていたため、現在はクローズされています。
要点は、現在処理中のリクエスト/遷移 (この 2 つは類似しています) に関して必要な追加データを保存するための状態オブジェクトが場所に用意されるようになったことです。
- サーバーでは、一度に1つのリクエストを処理するため、データを含む静的な場所を作成します。
req.body
- クライアントでは、状態オブジェクト (抽出されたフォーム データを含む) を に渡します
transitionTo()
。
これで、トランジション フックは両方の環境で同じフォーム データを受信できるようになりました。うまくいけば素晴らしいです。うまくいかない場合は、エラーを渡してフォームを再度レンダリングする方法が必要です。ここでも新しい状態オブジェクトが役に立ちます。transition.redirect()
入力データとエラーの両方を使用して渡すと、両側でレンダリングするために必要なものがすべて揃います。
v1.0 はまだベータ版であり、v0.13.x にはこれを行うために必要な API がないため、現時点ではこれ以上具体的な詳細には触れませんが、上記のプル リクエストを使用して 0.13.x でこのワークフローを実装するリポジトリがありますので、その間に参照してください。
- 同形ラボ- README には、各要素がどのように組み合わされているかの概要が記載されています。
以下に、プロセスの大まかなフロー図をいくつか示します。
エラーと再表示を伴うサーバーPOST
エラーと再表示を伴うクライアントPOST
このシナリオに関連する再利用可能なモジュールもいくつか作成しました。
- フォームデータを取得するフォームの入力から、POST された形式でデータを取得します。
- 反応自動フォームを提供し
<AutoForm>
、これを の代わりに使用して、<form>
フォームの入力からのすべてのデータをハンドラへの引数として受け取ることonSubmit
ができます。 - 反応ルーターフォームこれは、
<form>
React Router のに<Link>
相当します<a>
。指定された への遷移をトリガーしaction
、 (フォーム データ) 状態method
を渡しbody
ます。これは、まもなく v1.0 に更新されます。