javascript - 在reactjs中创建2个对象之间的关系(OnetToMany)

标签 javascript reactjs api spring-boot

我在 MYSQL 中创建了一个数据库,其中有两个表(Patient、Caregiver),它们在 Spring Boot 中通过 OneToMany 映射连接。我想在前端的 React Js 中创建一个患者对象(但我需要在创建时指定护理人员),然后将其发送到后端,我唯一的问题是我不确定如何创建连接。

我尝试为患者的护理人员引用创建一个选择选项,以便从护理人员列表中进行选择。但我无法这样做,因为收到错误:## 类型错误:无法获取未定义或空引用的属性“名称”##

我的护理人员和患者实体穿着 Spring Boot

@Entity
@Table(name = "Patient", schema = "mydbps")
public class Patient {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idPatient", unique = true, nullable = false)
    private int idPatient;

    @Column(name = "patientName")
    private String patientName;

    @Column(name = "patientSurname")
    private String patientSurname;

    @Column(name = "patientGender")
    private String patientGender;

    @Column(name = "patientBirthdate")
    private Date patientBirthdate;

    @Column(name = "patientAddress")
    private String patientAddress;

    @Column(name = "patientEmail")
    private String patientEmail;

    @Column(name = "patientPassword")
    private String patientPassword;

    @ManyToOne
    @JoinColumn(name = "Caregiver_idCaregiver")
    Caregiver Caregiver_idCaregiver;
}

@Entity
@Table(name="Caregiver",schema="mydbps")
public class Caregiver {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idCaregiver", unique=true, nullable = false)
    private int idCaregiver;

    @Column(name="caregiverName")
    private String caregiverName;

    @Column(name="caregiverSurname")
    private String caregiverSurname;

    @Column(name="caregiverGender")
    private String caregiverGender;

    @Column(name="caregiverAddress")
    private String caregiverAddress;

    @Column(name="caregiverBirthdate")
    private String caregiverBirthdate;

    @Column(name="caregiverEmail")
    private String caregiverEmail;

    @Column(name="caregiverPassword")
    private String caregiverPassword;

    @JsonIgnore
    @OneToMany(mappedBy = "Caregiver_idCaregiver", cascade = CascadeType.ALL,fetch= FetchType.LAZY)
    private Set<Patient> patientList;}

Controller :

@RestController
@CrossOrigin
@RequestMapping(value = "/caregivers")
public class CaregiverController {
    @Autowired
    private CaregiverService docService;

    @PostMapping
    public ApiResponse<Caregiver> saveUser(@RequestBody CaregiverDTO user){
        return new ApiResponse<>(HttpStatus.OK.value(), "Caregiver saved successfully.",docService.insert(user));
    }

    @GetMapping
    public ApiResponse<List<Caregiver>> listUser(){
        return new ApiResponse<>(HttpStatus.OK.value(), "Caregivers list fetched successfully.",docService.findAll());
    }

    @GetMapping("/{id}")
    public ApiResponse<Caregiver> getOne(@PathVariable int id){
        return new ApiResponse<>(HttpStatus.OK.value(), "Caregiver fetched successfully.",docService.findCaregiverByIdCaregiver(id));
    }

    @PutMapping("/{id}")
    public ApiResponse<CaregiverDTO> update(@RequestBody CaregiverDTO userDto) {
        return new ApiResponse<>(HttpStatus.OK.value(), "Caregiver updated successfully.",docService.update(userDto));
    }

    @DeleteMapping("/{id}")
    public ApiResponse<Void> deleteUser(@PathVariable int id) {
        docService.deleteUser(docService.findCaregiverByIdCaregiver(id));
        return new ApiResponse<>(HttpStatus.OK.value(), "Caregiver deleted successfully.", null);
    }


@RestController
@CrossOrigin
@RequestMapping(value = "/patients")
public class PatientController {


    @Autowired
    private PatientService docService;

    @PostMapping
    public ApiResponse<Patient> saveUser(@RequestBody PatientDTO user){
        return new ApiResponse<>(HttpStatus.OK.value(), "User saved successfully.",docService.insert(user));
    }

    @GetMapping
    public ApiResponse<List<Patient>> listUser(){
        return new ApiResponse<>(HttpStatus.OK.value(), "User list fetched successfully.",docService.findAll());
    }

    @GetMapping("/{id}")
    public ApiResponse<Patient> getOne(@PathVariable int id){
        return new ApiResponse<>(HttpStatus.OK.value(), "User fetched successfully.",docService.findPatientByIdPatient(id));
    }

    @PutMapping("/{id}")
    public ApiResponse<PatientDTO> update(@RequestBody PatientDTO userDto) {
        return new ApiResponse<>(HttpStatus.OK.value(), "User updated successfully.",docService.update(userDto));
    }

    @DeleteMapping("/{id}")
    public ApiResponse<Void> deleteUser(@PathVariable int id) {
        docService.deleteUser(docService.findPatientByIdPatient(id));
        return new ApiResponse<>(HttpStatus.OK.value(), "User deleted successfully.", null);
    }




}

React js 添加病人组件

import React, { Component } from 'react'
import PatientApiService from "../../service/PatientApiService";
import CaregiverApiService from "../../service/CaregiverApiService";
import Select from 'react-select';

class AddPatientComponent extends Component{

    constructor(props){
        super(props);
        this.state ={
            patientName: '',
            patientSurname: '',
            patientEmail: '',
            patientPassword: '',
            patientGender: '',
            patientAddress: '',
            Caregiver_idCaregiver: '',
            caregivers: [],
            message: null
        }
        this.saveUser = this.saveUser.bind(this);
    }

  componentDidMount() {
        this.reloadCaregiverList();

    }
  reloadCaregiverList() {
            PatientApiService.fetchCaregivers()
                .then((res) => {
                    this.setState({caregivers: res.data.result})
                });
        }

    saveUser = (e) => {
        e.preventDefault();
        let user = {patientName: this.state.patientName, patientSurname: this.state.patientSurname, patientEmail: this.state.patientEmail, patientPassword: this.state.patientPassword, patientGender: this.state.patientGender, patientAddress: this.state.patientAddress,Caregiver_idCaregiver :this.state.Caregiver_idCaregiver};
        PatientApiService.addUser(user)
            .then(res => {
                this.setState({message : 'Patient added successfully.'});
                this.props.history.push('/patients');
            });
    }

    onChange = (e) =>
        this.setState({ [e.target.name]: e.target.value });

    render() {
        return(
            <div>
            <div>
                <h2 className="text-center">Add User</h2>
                <form>
                <div className="form-group">
                    <label>Name:</label>
                    <input type="text" placeholder="patientName" name="patientName" className="form-control" value={this.state.patientName} onChange={this.onChange}/>
                </div>

                <div className="form-group">
                    <label>Surname:</label>
                    <input type="patientSurname" placeholder="patientSurname" name="patientSurname" className="form-control" value={this.state.patientSurname} onChange={this.onChange}/>
                </div>

                <div className="form-group">
                    <label>Email:</label>
                    <input placeholder="Email" name="patientEmail" className="form-control" value={this.state.patientEmail} onChange={this.onChange}/>
                </div>

                <div className="form-group">
                    <label>Password:</label>
                    <input placeholder="Password" name="patientPassword" className="form-control" value={this.state.patientPassword} onChange={this.onChange}/>
                </div>

                <div className="form-group">
                    <label>Gender:</label>
                    <input placeholder="Gender" name="patientGender" className="form-control" value={this.state.patientGender} onChange={this.onChange}/>
                </div>

                <div className="form-group">
                    <label>Address:</label>
                    <input placeholder="Address" name="patientAddress" className="form-control" value={this.state.patientAddress} onChange={this.onChange}/>
                </div>

             <div className="form-group">
                 <div className="row">
                   <div className="col-md-4"></div>
                   <div className="col-md-4">
                   <label>Caregiver:</label>
                    <Select options={ this.state.caregivers } name="Caregiver_idCaregiver"  value={this.state.Caregiver_idCaregiver} onChange={(e)=>this.setState({ Caregiver_idCaregiver:e.value})} />

                   </div>
                   <div className="col-md-4"></div>
                 </div>
               </div>

                <button className="btn btn-success" onClick={this.saveUser}>Save</button>
            </form>
    </div>
     <div>
                                <h2 className="text-center">Caregiver Details</h2>
                                <table className="table table-striped">
                                    <thead>
                                        <tr>
                                            <th className="hidden">Id</th>
                                            <th>FirstName</th>
                                            <th>LastName</th>
                                            <th>caregiverEmail</th>
                                            <th>caregiverGender</th>
                                            <th>caregiverAddress</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                        {
                                            this.state.caregivers.map(
                                        caregiver =>
                                                    <tr key={caregiver.idCaregiver}>
                                                        <td>{caregiver.caregiverName}</td>
                                                        <td>{caregiver.caregiverSurname}</td>
                                                        <td>{caregiver.caregiverEmail}</td>
                                                        <td>{caregiver.caregiverGender}</td>
                                                        <td>{caregiver.caregiverAddress}</td>
                                                    </tr>
                                            )
                                        }
                                    </tbody>
                                </table>

                            </div>
                            </div>
        );
    }
}

export default AddPatientComponent;

ApiPatient 服务:

import axios from 'axios';

const USER_API_BASE_URL = 'http://localhost:8080/patients';
const CAREGIVER_API_BASE_URL='http://localhost:8080/caregivers';
class PatientApiService {

    fetchUsers() {
        return axios.get(USER_API_BASE_URL);
    }

    fetchUserById(userId) {
        return axios.get(USER_API_BASE_URL + '/' + userId);
    }

    deleteUser(userId) {
        return axios.delete(USER_API_BASE_URL + '/' + userId);
    }

    addUser(user) {
        return axios.post(""+USER_API_BASE_URL, user);
    }

    editUser(user) {
        return axios.put(USER_API_BASE_URL + '/' + user.id, user);
    }
    fetchCaregivers()
    {return axios.get(CAREGIVER_API_BASE_URL);}

}

export default new PatientApiService();

我的 postman 获得 fetchCaregivers 的服务响应是:


    "status": 200,
    "message": "Caregivers list fetched successfully.",
    "result": [
        {
            "idCaregiver": 1,
            "caregiverName": "Marius",
            "caregiverSurname": "Ioan",
            "caregiverGender": null,
            "caregiverAddress": null,
            "caregiverBirthdate": null,
            "patientList": []
        }
    ]
}

但它不会出现在下拉列表中。

我希望从下拉列表中选择看护者,但我没有出现,运行时出现的错误是:

×
TypeError: Unable to get property 'name' of undefined or null reference
onChange
D:/AN 4/react-js-example-master/src/component/patient/AddPatientComponent.jsx:46
  43 | }
  44 | 
  45 | onChange = (e) =>
> 46 |     this.setState({ [e.target.name]: e.target.value });
     | ^
  47 | 
  48 | render() {
  49 |     return(

谢谢!

最佳答案

首先确保您的 React-Select 选项是一个对象数组,并且至少包含每个选项的值和标签属性,如下所示:

    [
        {value:'value1', label:'label1', otherProperty:'otherProperty1'},
        {value:'value2', label:'label2', otherProperty:'otherProperty2'}
    ]

为此(假设 PatientApiService.fetchCaregivers() 返回护理人员数组)创建一个 renderOptions 方法:

renderOptions=(options)=>{
    return options.map(option=>{
        return {value: option.idCaregiver , label:option.caregiverName}
    })
}

接下来请记住:“React-Select”不会返回典型的事件对象,例如:

{target:{value:'value' , label:'label' , name:'name'}}

相反,它会返回您作为选项传递给 options 属性的任何内容,例如:

{value:'value' , label:'label'}

因此,访问 e.target 将导致 undefined,此外,如果您尝试访问 e.target.name,您将收到错误,因为您无法访问 undefined 的 .name。

此外,您也无法直接提取字段的名称(因为这不是 react 选择返回对象的属性),除非您在选项中显式传递它,例如:

{value:'value1', label:'label1' , name:'someFieldName' , otherProperty:'otherProperty'}

如果您不想更改为普通选择标签,那么您需要:

  1. 修改react-select组件的onChange,使其与其他onChange事件的格式相同
  2. 使用上面的 renderOptions 方法
  3. 删除 value 属性,因为 react 选择会为您跟踪

更新后的选择现在应该是:

<Select 
    name="Caregiver_idCaregiver"//not stricly necessary 
    options={ this.formatOptions(this.state.caregivers) } 
    onChange={(e)=>this.onChange({target:{...e , name:'Caregiver_idCaregiver'}})}
/>

另外

您的 PatientApiService 没有您在 AddPatientComponentsaveUser 方法中调用的方法 saveUser您需要更改它以匹配您在 PatientApiService

中定义的 editUseraddUser 方法

例如添加用户:

saveUser = (e) => {
    e.preventDefault();
    let user = {patientName: this.state.patientName, patientSurname: this.state.patientSurname, patientEmail: this.state.patientEmail, patientPassword: this.state.patientPassword, patientGender: this.state.patientGender, patientAddress: this.state.patientAddress,Caregiver_idCaregiver :this.state.Caregiver_idCaregiver};
    PatientApiService.addUser(user)
        .then(res => {
            this.setState({message : 'Patient added successfully.'});
            this.props.history.push('/patients');
        });
}

简化的工作示例:

import React from 'react';
import ReactDOM from 'react-dom'
import Select from 'react-select';

class SomeComponent extends React.Component {
    state={
        caregivers:[ { idCaregiver: '1', caregiverName: 'User1', otherData:'data1'}, { idCaregiver: '2', caregiverName: 'User2', otherData:'data2' },],
        Caregiver_idCaregiver:''
    }

    saveUser = (e) => {
        e.preventDefault();

        const user = {Caregiver_idCaregiver : this.state.Caregiver_idCaregiver};
        const foundCaregiverObj = this.state.caregivers.find(caregiver=> caregiver.idCaregiver === this.state.Caregiver_idCaregiver)

        console.log(user)
        console.log(foundCaregiverObj)
    }

    onChange = (e) =>{
        this.setState({ [e.target.name]: e.target.value });
    }

    renderOptions=(options)=>{
        return options.map(option=>{
            return {value: option.idCaregiver , label:option.caregiverName}
        })
    }
    render(){
        return (
            <div>
                <label>Caregiver:</label>
                <Select options={ this.renderOptions(this.state.caregivers) } name="Caregiver_idCaregiver"  onChange={(e)=>this.onChange({target:{...e , name:'Caregiver_idCaregiver'}})}/>
                <button onClick={this.saveUser}>Save</button>
            </div>
        )
    }
}

ReactDOM.render(
    <SomeComponent />,
    document.getElementById("root")
);

关于javascript - 在reactjs中创建2个对象之间的关系(OnetToMany),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58487150/

相关文章:

javascript - CDATA 真的有必要吗?

javascript - 具有一流功能的语言是否一定允许闭包?

javascript - 如何解决 Typescript 中关于 `withStateHandlers` 的错误

c# - 您如何管理网络服务的变更?

image - golang api 图像下载中的图像文件损坏

javascript - 如何用正则表达式匹配JS中后面的字符串,但不包括单词字符?

javascript - 在 javascript 中创建对象(使用 new)有什么优点?

javascript - 流量: "Cannot access computed property using undefined [1]" when using default props for functional react components

reactjs - Vue/ react : Proper way to call functions to pass down data?

javascript - 在 JavaScript 中,console.log 为我提供了 for 循环中的每个值。但是 var.text 仅显示最后一个值。为什么是这样?