You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 05:20:50