javascript - React 组件在状态更改时重新渲染

标签 javascript reactjs material-ui

我的表单之前工作得很好,现在经过几次更改后,输入字段的状态更改正在失去焦点。我正在使用 MUI,它之前工作得很好,但在状态变量名称发生一些细微变化后,它突然开始失去焦点。我认为这不是问题,但我不知道为什么会发生这种情况,因为我认为所有受控表单都是这样制作的

import { useEffect, useState } from "react";
import Axios from "axios";
import { Schedule } from "./Schedule";
import { PageHeader } from "./PageHeader";
import { Button, TextField, styled, CircularProgress } from "@mui/material";
import FileUploadIcon from "@mui/icons-material/FileUpload";
import { DesktopDatePicker } from "@mui/x-date-pickers/DesktopDatePicker";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider/LocalizationProvider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import SendIcon from "@mui/icons-material/Send";

function Form() {
  const [formData, setFormData] = useState({ startTime: "", endTime: "" });
  const [file, setFile] = useState("");
  const [data, setData] = useState("");
  const [newValue, setValue] = useState(null);
  const [loading, setLoading] = useState(false);
  console.log(formData);
  console.log("Rerendered");

  function handleChange(event) {
    setFormData((previousFormData) => {
      return {
        ...previousFormData,
        [event.target.name]: event.target.value,
      };
    });
  }

  function handleClick(event) {
    setLoading(true);
    event.preventDefault();
    setTimeout(() => {
      const postFormData = new FormData();
      postFormData.append("startTime", formData.startTime);
      postFormData.append("endTime", formData.endTime);
      postFormData.append("date", newValue);
      postFormData.append("file", file);

      Axios.post("http://localhost:3001/aip", postFormData, {
        headers: {
          "Access-Control-Allow-Origin": "cors",
        },
      })
        .then((res) => setData(res.data))
        .then(setLoading(false))
        .catch((err) => console.log(err));
    }, 2000);
  }

  const Container = styled("main")({
    marginTop: 50,
    display: "grid",
    justifyItems: "center",
  });
  const Div = styled("div")({
    display: "flex",
    gap: 50,
  });
  const Form = styled("form")({
    border: "none",
    width: "100%",
    height: "100%",
    margin: "auto",
    display: "grid",
    justifyItems: "center",
    gap: 50,
  });

  return (
    <>
      <PageHeader />
      <Container>
        <Form onSubmit={handleClick} encType="multipart/form-data">
          <Div class="timeInput">
            <TextField
              label="From"
              name="startTime"
              variant="outlined"
              placeholder="9:00"
              onChange={handleChange}
              value={formData.startTime}
              required
            />
            <TextField
              label="To"
              name="endTime"
              variant="outlined"
              placeholder="9:30"
              onChange={handleChange}
              value={formData.endTime}
              required
            />
          </Div>
          <div class="dateInput">
            <LocalizationProvider dateAdapter={AdapterDayjs}>
              <DesktopDatePicker
                value={newValue}
                label="Choose Date"
                onChange={(newValue) => setValue(newValue)}
                renderInput={(params) => <TextField {...params} />}
              />
            </LocalizationProvider>
          </div>
          <Div>
            <Button sx={{ gap: 2 }} variant="contained" component="label">
              Upload Schedule
              <input
                hidden
                accept=".xlsx"
                multiple
                type="file"
                onChange={(event) => {
                  const file = event.target.files[0];
                  setFile(file);
                }}
              />
              <FileUploadIcon />
            </Button>
            <Button sx={{ gap: 2 }} variant="contained" component="label">
              Search
              <input hidden type="submit" />
              <SendIcon />
            </Button>
          </Div>
        </Form>
      </Container>
      {loading ? (
        <CircularProgress sx={{ alignItems: "center" }} />
      ) : (
        <Schedule data={data} />
      )}
    </>
  );
}

export default Form;

最佳答案

在此示例中,每当 react 状态发生变化时,App将重新渲染。因为App重新渲染,Form被重新声明并且底层 DOM 节点 ( form ) 的内部状态丢失。

export default function App() {
  const [value, setValue] = useState("");
  const Form = styled("form")({});
  return (
    <Form>
      <input value={value} onChange={({ target }) => setValue(target.value)} />
    </Form>
  );
}

Edit quizzical-forest-ti6bb7

声明Form App 体外它有效

export default function App() {
  const [value, setValue] = useState("");
  return (
    <Form>
      <input value={value} onChange={({ target }) => setValue(target.value)} />
    </Form>
  );
}

const Form = styled("form")({});

Edit kind-blackburn-lfj8sd

如果您必须申报FormApp 的体内(你可能不需要),你可以用 React.useMemo 来内存它

export default function App() {
  const [value, setValue] = useState("");
  const Form = useMemo(() => styled("form")({}), []);
  return (
    <Form>
      <input value={value} onChange={({ target }) => setValue(target.value)} />
    </Form>
  );
}

Edit react FC inside FC with useMemo

关于javascript - React 组件在状态更改时重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75107084/

相关文章:

javascript - django 如何在模板中包含 javascript

javascript - 在 asp.net 文本框中键入内容时自动添加点 (.)(将文本框格式设置为小数点后两位)

javascript - 为什么我的状态没有在此组件中设置

reactjs - 如何从 material-ui react 中更改 Paper 组件的边框颜色?

javascript - Bootstrap : show/hide column divs with checkbox and change column span

javascript - Backbone.js - 如何将非状态 "event"从一个 View 发送到另一个 View ?

javascript - 使用草稿js的Nextjs-当我使用convertFromHTML方法使用HTML内容初始化编辑器时未定义文档

javascript - 在 React 中的 .map 迭代中的单个元素上使用 onMouseEnter

material-ui - 使用 material-ui 表和 react-beautiful-dnd

reactjs - 如何修复文件上传输入的上传图标( Material UI)