javascript - 在同构反应+ 反应路由器应用中,如何处理Post请求

  显示原文与译文双语对照的内容
101 3

我想构建同构的react + react-router 应用程序,经过几天的谷歌,现在我可以实现同构应用,只处理获取请求。

以下是我到目前为止所做的:

  • 服务器使用 react-router 处理所有请求
  • react-router 将调用位于每个与路由匹配的React视图中的fetchData 函数。
  • 将之前获取的数据设置为React视图的道具并将它的呈现到 string
  • 在HTML中插入 string 和获取的数据作为全局变量 window.__STATE__,并将HTML传递给客户端
  • 我们已经从服务器成功地呈现了 React App
  • 当客户端完成 React App javascript的加载时,它将尝试渲染。 但是我们将状态从 window.__STATE__ 作为 React App的道具传递出来,React不会被呈现,因为状态是相同的。

问题是 POST/PUT/DELETE/WHATEVER 请求不能使用它。 处理获取请求时,react-router 有关于 paramsquery的信息。 例如如果我们有一条路线: /user/:uid 和客户端请求这里 url: /user/1?foo=bar,那么 params 是: {uid: 1}query 将是 {foo:'bar'}

react-router 可以将它传递给 fetchData 函数,这样它就会知道用 1的uid 来获取用户并执行 foo 查询。

在POST请求中,react-router 不知道POST参数。 当然,我们可以把POST参数传递给 fetchData 函数,但是客户端又如何? 它不知道POST参数是什么。

服务器是否可以告诉客户关于POST参数的信息? below 是我的登录视图的一个例子。 当用户提交表单时,服务器将在错误中呈现错误信息,或者将它的重定向到成功的仪表板。

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


...


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


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);


 }


 }


}



时间: 原作者:

...