将数据从 ReactJS 表单传递到 Rails API 会导致应用程序崩溃

问题描述 投票:0回答:1

作为前提,这是我第一次使用 React 作为前端、Rails 作为后端创建 Web 应用程序,因此对于任何巨大的错误,我提前表示歉意。我尝试寻找同样的问题,但尚未找到任何解决方案。

问题:

我有一张包含员工数据的表。为了添加新员工,我从 React 中的表单收集数据,并向 Rails API 发出 POST 请求。数据成功保存在后端后,我希望应用程序使用新添加的员工重新渲染表。
现在,数据已成功从 React 传输到 API 并正确保存在后端,但是保存数据后,一切都会崩溃,并且表不会重新渲染,除非经过一段时间(<1 min).

代码:

这是员工控制器(为了简单起见,我只发布了创建函数):

#employees_controller.rb

class Api::V1::EmployeesController < ApplicationController

# POST /employees
  def create
    @employee = Employee.new(employee_param)

    if @employee.save!
      render json: @employee, status: :created, location: api_v1_employees_path(@employee)
    else
      render json: @employee.errors, status: :unprocessed_entity
    end
  end

 private

  def employee_param
    params.require(:employee).permit(:fullname, :email, :phone_number, :company, :is_admin)
  end

end

我认为它工作得很好,因为数据已成功保存在正确的位置,并且我可以看到它们显示在索引中。

这是显示员工数据的 React 表:

// DataTable.js
// DataTable component (shows the employees data)
import React from "react";

import {
  TableContainer,
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableRow,
} from "@mui/material";
import { withStyles } from "@material-ui/core/styles";

const StyledTableHeaderCell = withStyles({
  root: {
    color: "#232020",
    fontSize: "12px",
    fontWeight: "bold",
    lineHeight: "150%",
    fontFamily: "Poppins",
  },
})(TableCell);

const StyledTableCell = withStyles({
  root: {
    color: "#232020",
    fontSize: "12px",
    lineHeight: "150%",
    fontFamily: "Poppins",
  },
})(TableCell);

function DataTable({ header, employeesData }) {
  console.log(typeof employeesData);
  console.log(employeesData);
  return (
    <TableContainer
      sx={{
        maxHeight: 440,
        minWidth: 650,
        overflow: "auto",
        width: "95%",
        marginTop: "37px",
        borderRadius: "10px",
        border: "1px solid #E6EDFF",
      }}
    >
      <Table stickyHeader aria-label="sticky table">
        <TableHead sx={{ display: "table-header-group" }}>
          <TableRow>
            {header.map((field, idx) => {
              return { idx } === 0 ? (
                <StyledTableHeaderCell key={idx}>{field}</StyledTableHeaderCell>
              ) : (
                <StyledTableHeaderCell align="right" key={idx}>
                  {field}
                </StyledTableHeaderCell>
              );
            })}
          </TableRow>
        </TableHead>

        <TableBody>
          {employeesData.map((employee, idx) => {
            return (
              <TableRow
                key={idx}
                sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
              >
                <StyledTableHeaderCell component="th" scope="row">
                  {employee.fullname}
                </StyledTableHeaderCell>
                <StyledTableCell align="right">
                  {employee.company}
                </StyledTableCell>
                <StyledTableCell align="right">
                  {employee.email}
                </StyledTableCell>
                <StyledTableCell align="right">
                  {employee.phone_number}
                </StyledTableCell>
                <StyledTableCell align="right">
                  {employee.is_admin ? "Admin" : "Tecnico"}
                </StyledTableCell>
              </TableRow>
            );
          })}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

export default DataTable;

其中对象EmployeeData作为该组件的道具传递:

// Employees.js
// Employees index

import React from "react";
import axios from "axios";
import { useEffect, useState } from "react";

import DataTable from "../shared/DataTable";
import BtnContainer from "../components/buttonsdiv";

import Box from "@mui/material/Box";

const API_URL = "http://localhost:3000/api/v1/employees";

function getAPIData(params) {
  return axios.get(API_URL).then((response) => response.data);
}

function EmployeesPage() {
  const [employees, setEmployees] = useState();

  useEffect(() => {
    let mounted = true;
    getAPIData().then((items) => {
      if (mounted) {
        setEmployees(items);
      }
    });
    return () => (mounted = false);
  }, []);

  // Callback function to receive data from the child component
  const handleFormSubmit = (data) => {
    setEmployees((prev) => ({ ...prev, data }));
  };

  return (
    <Box>
      // the component BtnContainer contains the button that triggers the form that gets the employee data and the form itself
          <BtnContainer
            apiURL={API_URL}
            text="Aggiungi impiegato"
            onFormSubmit={handleFormSubmit}
            formTitle="Aggiungi nuovo impiegato"
          />
          {employees === undefined ? (
            <p>Loading...</p>
          ) : (
            // DataTable is the table that displays the employees data
            <DataTable
              header={["Nome", "Società", "Email", "Telefono", "Ruolo"]}
              employeesData={employees}
            />
          )}

    </Box>
  );
}

export default EmployeesPage;

我的假设和我已经尝试过的:

我认为问题在于,一旦我将数据发送到 API 并重新渲染页面,员工对象仍然没有填充数据,因此它是未定义的。我尝试添加一个条件,如果对象未定义而不是表,它会显示正在加载的东西,但它不起作用。所以我有点迷失:,)

reactjs ruby-on-rails forms asynchronous
1个回答
0
投票

通过替换这一行解决了问题

setEmployees((prev) => ({ ...prev, data }));

有了这个

setEmployees((prev) => [...prev, data]);

在Employees.js 文件中。

© www.soinside.com 2019 - 2024. All rights reserved.