javascript 如何在同构 React + React Router 应用程序中处理 Post 请求
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31079158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Handle Post Request in Isomorphic React + React Router Application
提问by Riko Nagatama
I want to build Isomorphic react
+ react-router
application and after a few days googling, now I can achieve isomorphic application that only handles GET request.
我想构建同构react
+react-router
应用程序,经过几天的谷歌搜索,现在我可以实现只处理GET请求的同构应用程序。
Here's what I've done so far:
这是我到目前为止所做的:
- Server use
react-router
to handle all request react-router
will callfetchData
functions that resides in each React View that matches the route.- Set the data fetched before into props of the React View and render it into
string
- Inject the
string
and data fetched before as global variablewindow.__STATE__
into HTML and deliver the HTML to the client - We have successfully render React App from the server
- When the client finished loading our React App javascript, it will try to render. But we pass the state from
window.__STATE__
as the props of our React App, and React will not re-render because the state is the same
- 服务器用于
react-router
处理所有请求 react-router
将调用fetchData
驻留在与路由匹配的每个 React 视图中的函数。- 将之前获取的数据设置为 React View 的 props 并将其渲染为
string
- 将
string
之前获取的数据和数据作为全局变量window.__STATE__
注入到 HTML 中,并将 HTML 传递给客户端 - 我们已经成功地从服务器渲染了 React App
- 当客户端完成加载我们的 React App javascript 时,它会尝试渲染。但是我们将 state from
window.__STATE__
作为我们 React App 的 props传递,React 不会重新渲染,因为 state 是相同的
The problem is it will not work with POST/PUT/DELETE/WHATEVER request. When handling GET request, react-router
have information about params
and query
. For example if we have a route: /user/:uid
and client request this url: /user/1?foo=bar
, then params
would be: {uid: 1}
and query
would be {foo: 'bar'}
问题是它不适用于 POST/PUT/DELETE/WHATEVER 请求。处理 GET 请求时,react-router
获取有关params
和 的信息query
。例如,如果我们有一个 route:/user/:uid
并且客户端请求这个 url: /user/1?foo=bar
,那么params
将是:{uid: 1}
并且query
将是{foo: 'bar'}
react-router
then can pass it down to fetchData
function so it will know to fetch user with uid
of 1 and do whatever with foo
query.
react-router
然后可以将它传递给fetchData
函数,以便它知道使用uid
1获取用户并使用foo
查询执行任何操作。
While in POST request, react-router
doesn't know about the POST parameters. On Server, of course we could pass the POST parameters to fetchData
function, but what about the Client? It doesn't know what the POST parameters are.
在 POST 请求中,react-router
不知道 POST 参数。在服务器上,当然我们可以将 POST 参数传递给fetchData
函数,但是客户端呢?它不知道 POST 参数是什么。
Is there a way that the server could tell the Client about the POST parameters? Below is an example of my Login View. I want when user submit the form, the server will render error message on error, or redirect it to dashboard on success.
有没有办法让服务器可以告诉客户端有关 POST 参数的信息?下面是我的登录视图的示例。我希望当用户提交表单时,服务器会在出错时呈现错误消息,或者在成功时将其重定向到仪表板。
fetchData.js
fetchData.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);
}
server.js
服务器.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
// ...
})
});
});
...
login.jsx
登录.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);
}
}
}
回答by Jonny Buchanan
Getting "POST" data on the client
在客户端获取“POST”数据
On the client side, you get POST data by extracting values from your form inputs in a way which corresponds to what you would have received on the server had the form been submitted normally.
在客户端,您通过从表单输入中提取值来获取 POST 数据,这种方式与如果表单正常提交时您在服务器上收到的内容相对应。
Using POST data
使用 POST 数据
So now you have your POST data, but you still have the problem that there's no way to feed the POST data into your transition hooks in React Router 0.13.x and earlier. I created a pull request for this featurewhich has now been closed because it was included as part of the rewrite for the upcoming v1.0 release.
所以现在你有了你的 POST 数据,但你仍然有问题,在 React Router 0.13.x 和更早的版本中,没有办法将 POST 数据提供给你的转换钩子。我为此功能创建了一个拉取请求,该请求现已关闭,因为它已包含在即将发布的 v1.0 版本的重写中。
The gist of it is that locations now have a state object for squireling away any extra data you need about the current request/transition (the two are analagous) being handled:
其要点是,位置现在有一个状态对象,用于收集有关正在处理的当前请求/转换(两者是类似的)所需的任何额外数据:
- On the server, you're dealing with one request at a time, so you create a static Location with data from
req.body
- On the client you pass the state object (containing extracted form data) to
transitionTo()
.
- 在服务器上,您一次处理一个请求,因此您使用来自
req.body
- 在客户端上,您将状态对象(包含提取的表单数据)传递给
transitionTo()
.
Now your transition hook is capable of receiving the same form data in both environments. If things go well, great! If things don't go well, you need a way to pass errors and re-render the form again. New state object to the rescue again! Use transition.redirect()
and pass both input data and errors and you now have everything you need to render on both sides.
现在您的转换挂钩能够在两种环境中接收相同的表单数据。如果一切顺利,那就太好了!如果事情进展不顺利,您需要一种方法来传递错误并再次重新呈现表单。新的状态对象再次救援!使用transition.redirect()
并传递输入数据和错误,您现在拥有在两侧渲染所需的一切。
I'm not going into more specific detail right now because v1.0 is still in beta and v0.13.x doesn't have the necessary API to do this anyway, but I have a repository which uses the pull request above to implement this workflow with 0.13.x which you could look at in the meantime:
我现在不讨论更具体的细节,因为 v1.0 仍处于测试阶段,而 v0.13.x 无论如何都没有必要的 API 来执行此操作,但我有一个使用上述拉取请求来实现的存储库您可以同时查看带有 0.13.x 的此工作流程:
- isomorphic-lab- the README gives an overview of how things fit together.
- isomorphic-lab- README 概述了事物如何组合在一起。
Here are some rough flow diagrams of the process, too:
以下是该过程的一些粗略流程图:
Server POST with errors and redisplay
服务器 POST 有错误并重新显示
Client POST with errors and redisplay
客户端 POST 有错误并重新显示
I've also created a few reusable modules related to this scenario:
我还创建了一些与此场景相关的可重用模块:
- get-form-datagets data from a form's inputs in the format it would have been POSTed in.
- react-auto-formprovides
<AutoForm>
, which you can use instead of<form>
to receive all the data from a form's inputs as an argument to itsonSubmit
handler - react-router-form, which is to
<form>
what React Router's<Link>
is to<a>
- it handles triggering a transition to the givenaction
, passingmethod
andbody
(form data) state - this will be updated for v1.0 soon.
- get-form-data从表单的输入中获取数据,其格式为 POST 格式。
- react-auto-form提供
<AutoForm>
,您可以使用它来代替<form>
从表单输入接收所有数据作为其onSubmit
处理程序的参数 - react-router-form,这就是
<form>
React Router 的<Link>
作用<a>
——它处理触发到给定action
、传递method
和body
(表单数据)状态的转换——这将很快更新到 v1.0。