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

React表单提交字段为空?React+Spring Boot项目问题求助

问题:React+Spring Boot POST请求后数据库仅生成自动ID,其余字段为空

正在学习React,做React+Spring Boot测试项目,每次发送POST请求时,数据库会生成自动ID,但catName、catDescription字段均为空。此前将表单属性从value改为defaultValue解决了表单不可编辑的问题,但字段为空的问题仍未解决。


前端React代码

export function withRouter(Children) {
    return (props) => {
        const match = { params: useParams() };
        return <Children {...props} match={match} />
    }
}
class CategoryEdit extends Component {

    emptyItem = {
        catName: '',
        catDescription: ''
    };

    constructor(props) {
        super(props);
        this.url = "http://localhost:8080/categories";
        this.state = {
            item: this.emptyItem
        };
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    async componentDidMount() {
        if (this.props.match.params.id !== 'add') {
            const category = await (await fetch(`${this.url}/${this.props.match.params.id}`)).json();
            this.setState({ item: category });
        }
    }

    handleChange(event) {
        const target = event.target;
        const value = target.value;
        const name = target.name;
        let item = { ...this.state.item };
        item[name] = value;
        this.setState({ item });
    }

    async handleSubmit(event) {
        event.preventDefault();
        const { item } = this.state;

        await fetch('http://localhost:8080/categories/add' + (item.id ? '/' + item.id : ''), {
            method: (item.id) ? 'PUT' : 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json',
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Credentials': true
            },
            body: JSON.stringify(item),
        });
   };
 
    render() {
        const { item } = this.state;
        const title = <h2>{item.id ? 'Edit Category' : 'Add Category'}</h2>;
        console.log(item);
        return <div>

            <Container>
                <AppNavBar />
                {title}
                <Form onSubmit={this.handleSubmit}>
                    <FormGroup>
                        <Label for="catName"> Category Name</Label>
                        <Input type="text" name="catName" id="catName" defaultValue ={item.catName || ''}
                            onChange={this.handleChange} autoComplete="catName" />
                    </FormGroup>
                    <FormGroup>
                        <Label for="catDescription">Description</Label>
                        <Input type="text" name="catDescription" id="catDescription" defaultValue ={item.catDescription || ''}
                            onChange={this.handleChange} autoComplete="catDescription" />
                    </FormGroup>
                    <FormGroup>
                        <Button color="primary" type="submit">Save</Button>{' '}
                        <Button color="secondary" tag={Link} to="/">Cancel</Button>
                    </FormGroup>
                </Form>
            </Container>
        </div>
    }
}
export default withRouter(CategoryEdit);

后端Spring Boot代码

控制器

@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/categories")
public class CategoryRestController {

    @Autowired
    CategoryService cs;
    
    @PostMapping("/add")
    public Category saveCat(Category cat) {
        return cs.addNewCategory(cat);
    }   
}

实体类

import lombok.Data;

@Data
@Entity
@Table(name = "category")
public class Category implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    private Integer catId;
    private String catName;
    private String catDescription;
}

服务类

@Service
public class CategoryService {

    @Autowired
    private CategoryRepository cr;
    
    public Category addNewCategory(Category category) {
        return cr.save(category);
    }
}

仓库接口

public interface CategoryRepository extends JpaRepository<Category, Integer> {
}   

解决方法

核心问题:后端未解析JSON请求体

前端通过fetch发送的是JSON格式的请求体,但后端控制器的saveCat方法参数Category cat没有添加@RequestBody注解,导致Spring无法将请求体中的JSON数据绑定到Category对象上,所以除了自动生成的catId外,其他字段都是默认空值。

修复步骤:

  1. 修改后端控制器方法,添加@RequestBody注解:
@PostMapping("/add")
public Category saveCat(@RequestBody Category cat) { // 新增@RequestBody
    return cs.addNewCategory(cat);
}
  1. 验证前端表单数据是否正确提交:
    在handleSubmit方法中,点击保存后查看浏览器控制台的console.log(item)输出,确认对象包含正确的catName和catDescription值。如果这里的值正确,加上@RequestBody后后端就能正确接收数据。

  2. 可选:将表单改为受控组件(符合React最佳实践)
    之前改用defaultValue解决了表单不可编辑问题,若handleChange逻辑正确,可改回value绑定实现受控组件:

// 替换Input的defaultValue为value
<Input type="text" name="catName" id="catName" value={item.catName}
       onChange={this.handleChange} autoComplete="catName" />
<Input type="text" name="catDescription" id="catDescription" value={item.catDescription}
       onChange={this.handleChange} autoComplete="catDescription" />

额外注意点

后端实体类的ID字段是catId,但前端state中用的是item.id,后续编辑功能需要注意字段名对应(比如后端返回catId时,前端需映射到item.id,或统一修改字段名保持一致),不过这不会影响当前POST新增请求。


内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:15:33