React表单无法调用Java Spring后端REST接口创建用户问题排查
问题
Java Spring后端API运行正常,通过curl发送POST请求可以成功创建新用户,但使用浏览器中的React表单提交时,用户数据无法存入数据库。相关代码如下:
App类创建用户的方法
// tag::create[] onCreate(newUser) { follow(client, root, ['users']).then(userCollection => { return client({ method: 'POST', path: userCollection.entity._links.self.href, entity: newUser, headers: {'Content-Type': 'application/json'} }) }).then(response => { return follow(client, root, [ {rel: 'users', params: {'size': this.state.pageSize}}]); }).done(response => { if (typeof response.entity._links.last !== "undefined") { this.onNavigate(response.entity._links.last.href); } else { this.onNavigate(response.entity._links.self.href); } }); } // end::create[]
创建数据填写弹窗的类
// tag::create-dialog[] class CreateDialog extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(e) { e.preventDefault(); const newUser = {}; this.props.attributes.forEach(attribute => { newUser[attribute] = ReactDOM.findDOMNode(this.refs[attribute]).value.trim(); }); this.props.onCreate(newUser); // clear out the dialog's inputs this.props.attributes.forEach(attribute => { ReactDOM.findDOMNode(this.refs[attribute]).value = ''; }); // Navigate away from the dialog to hide it. window.location = "#"; } render() { const inputs = this.props.attributes.map(attribute => <p key={attribute}> <input type="text" placeholder={attribute} ref={attribute} className="field"/> </p> ); return ( <div> <a href="#createUser">Create</a> <div id="createUser" className="modalDialog"> <div> <a href="#" title="Close" className="close">X</a> <h2>Create new user</h2> <form> {inputs} <button onClick={this.handleSubmit}>Create</button> </form> </div> </div> </div> ); } } // end::create-dialog[]
排查与解决
1. 补充错误捕获逻辑
原代码用.done()处理异步流程,但未添加错误捕获,请求失败(如跨域、后端参数校验不通过)时无法定位问题。修改后添加错误捕获:
onCreate(newUser) { follow(client, root, ['users']) .then(userCollection => { return client({ method: 'POST', path: userCollection.entity._links.self.href, entity: newUser, headers: {'Content-Type': 'application/json'} }) }) .then(response => { return follow(client, root, [ {rel: 'users', params: {'size': this.state.pageSize}}]); }) .then(response => { if (typeof response.entity._links.last !== "undefined") { this.onNavigate(response.entity._links.last.href); } else { this.onNavigate(response.entity._links.self.href); } }) .catch(err => { console.error('创建用户失败:', err); // 可添加前端错误提示,告知用户操作失败 }); }
2. 校验请求数据序列化与格式
- 打开浏览器开发者工具(F12)的Network面板,查看POST请求的Payload,确认发送的
newUser结构与curl请求完全一致(包括字段名、数据类型)。 - 如果使用的HTTP客户端不自动序列化JSON,需手动将
newUser转为JSON字符串:return client({ method: 'POST', path: userCollection.entity._links.self.href, entity: JSON.stringify(newUser), // 手动序列化 headers: {'Content-Type': 'application/json'} })
3. 替换过时的ReactDOM.findDOMNode
ReactDOM.findDOMNode已被官方标记为过时,建议改用受控组件管理输入值,避免依赖refs:
class CreateDialog extends React.Component { constructor(props) { super(props); // 初始化输入状态 const initialState = {}; props.attributes.forEach(attr => initialState[attr] = ''); this.state = initialState; this.handleSubmit = this.handleSubmit.bind(this); this.handleChange = this.handleChange.bind(this); } handleChange(e) { const { name, value } = e.target; this.setState({ [name]: value.trim() }); } handleSubmit(e) { e.preventDefault(); const newUser = {...this.state}; this.props.onCreate(newUser); // 清空输入 const emptyState = {}; this.props.attributes.forEach(attr => emptyState[attr] = ''); this.setState(emptyState); window.location = "#"; } render() { const inputs = this.props.attributes.map(attribute => <p key={attribute}> <input type="text" placeholder={attribute} name={attribute} value={this.state[attribute]} onChange={this.handleChange} className="field" /> </p> ); return ( <div> <a href="#createUser">Create</a> <div id="createUser" className="modalDialog"> <div> <a href="#" title="Close" className="close">X</a> <h2>Create new user</h2> <form onSubmit={this.handleSubmit}> {inputs} <button type="submit">Create</button> </form> </div> </div> </div> ); } }
4. 排查跨域问题
浏览器存在同源策略限制,即使curl请求正常,前端可能因跨域导致请求被拦截:
- 检查Network面板中是否有OPTIONS预检请求失败。
- 在Spring后端配置CORS,比如在Controller类上添加
@CrossOrigin注解,或通过全局配置允许前端域名的POST请求。
5. 优化表单提交事件绑定
原代码将提交事件绑定在按钮的onClick上,建议改为绑定在<form>的onSubmit事件,更符合HTML表单默认行为,避免意外触发提交。
内容的提问来源于stack exchange,提问作者Korneliusz93
相关产品推荐
相关产品推荐

