Javascript 在react钩子中执行之前正在更新的状态

Javascript 在react钩子中执行之前正在更新的状态,javascript,reactjs,frontend,react-hooks,Javascript,Reactjs,Frontend,React Hooks,我正在开发一个表单,它使用HOC获取输入(来自用户的多个图像和文本)。 下面是我的表单组件 import React from "react"; import Grid from "@material-ui/core/Grid"; import Typography from "@material-ui/core/Typography"; import Alert from "@material-ui/lab/Alert"; import TextField from "@material-ui

我正在开发一个表单,它使用HOC获取输入(来自用户的多个图像和文本)。 下面是我的表单组件

import React from "react";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Alert from "@material-ui/lab/Alert";
import TextField from "@material-ui/core/TextField";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import { Snackbar, IconButton } from "@material-ui/core";
import { Loading, Snackbars, UIButton, UITextField } from "../UI/index";
import {
  Paper,
  makeStyles,
  Button,
} from "@material-ui/core";

function Gallery(props) {
  let {
    submitHandler,
    selectImages,
    message,
    galleryForm,
    inputChangedHandler,
  } = props;

  return (
    <div>
      <Paper
        elevation={3}
        style={{ padding: "20px" }}
      >
        <form
          onSubmit={submitHandler}
          noValidate
          id="galleryForm"
        >
          <Grid container spacing={3}>
            <Grid item xs={12} md={6}>
              <UITextField
                name="imageTitle"
                label="Image Title"
                value={galleryForm.imageTitle.value}
                onChange={(event) => inputChangedHandler(event, "imageTitle")}
                error={galleryForm.imageTitle.invalid}
                helperText={galleryForm.imageTitle.helperText}
              />
            </Grid>
            <Grid item xs={12} sm={6}>
              <Grid container>
                <Grid>
                  <TextField
                    id="standard-basic"
                    fullWidth
                    label="Select File To Upload"
                    value={message}
                    error={galleryForm.images.invalid}
                    helperText={galleryForm.images.helperText}
                  />
                </Grid>
                <Grid>
                  <input
                    accept=".jpg , .png, .jpeg"
                    className={classes.input}
                    style={{ display: "none" }}
                    id="raised-file"
                    multiple
                    type="file"
                    onChange={selectImages}
                  />
                  <label htmlFor="raised-file">
                    <Button
                      variant="contained"
                      style={{
                        background: "#D3D3D3",
                        color: "black",
                        fontSize: "15px",
                        borderRedius: "4px",
                      }}
                      component="span"
                    >
                      UPLOAD PHOTOS
                    </Button>
                  </label>
                </Grid>
              </Grid>
            </Grid>
            <Grid className={classes.center}>
              <UIButton
                type="submit"
                variant="contained"
                color="primary"
                size="large"
                className={classes.submit}
              >
                create gallery
              </UIButton>
            </Grid>
          </Grid>
        </form>
      </Paper>
    </div>
  );
}

export default enhancer(Gallery);
从“React”导入React;
从“@material ui/core/Grid”导入网格;
从“@material ui/core/Typography”导入排版;
从“@material ui/lab/Alert”导入警报;
从“@material ui/core/TextField”导入TextField;
从“@material ui/core/FormControlLabel”导入FormControlLabel;
从“@material ui/core”导入{Snackbar,IconButton}”;
从“./UI/index”导入{Loading,snackbar,UIButton,UITextField};
进口{
纸张
制作风格,
按钮
}来自“@材料界面/核心”;
功能画廊(道具){
让{
服从者,
选择图像,
消息
厨房式,
inputChangedHandler,
}=道具;
返回(
inputChangedHandler(事件,“imageTitle”)}
错误={galleryForm.imageTitle.invalid}
helperText={galleryForm.imageTitle.helperText}
/>
上传照片
创建图库
);
}
导出默认增强器(库);
下面是我的HOC(增强器),它接受Gallery组件

import React, { useEffect, useState } from "react";
import { compose } from "redux";
import Gallery from "./index";
import galleryFiled from "./galleryField";

export let enhancer = compose((Gallery) => ({ ...props }) => {
  const [galleryForm, setGalleryForm] = useState(galleryFiled);
  const [message, setMessage] = useState("");

  const selectImages = (event) => {
    const updatedForm = {
      ...galleryForm,
    };
    console.log("check:", galleryForm);
    for (var i = 0; i < event.target.files.length; i++) {
      if (event.target.files.item(i).name.match(/\.(jpg|jpeg|png)$/)) {
        updatedForm.images.value.push(event.target.files.item(i));
      }
    }

    setGalleryForm({ ...updatedForm });
    let message = `${updatedForm.images.value.length} valid image(s) selected`;
    console.log(galleryForm);
    setMessage(message);
  };

  const inputChangedHandler = (event, inputIdentifier) => {
    const updatedForm = {
      ...galleryForm,
    };
    console.log(updatedForm);
    updatedForm[inputIdentifier].value = event.target.value;
    updatedForm[inputIdentifier].invalid = false;
    updatedForm[inputIdentifier].helperText = "";
    console.log(updatedForm);
    setGalleryForm({
      ...updatedForm,
    });
    console.log(galleryForm);
  };

  const clearForm = (event) => {
    let allFormKeys = Object.keys(galleryForm);
    let formData = { ...galleryForm };
    allFormKeys.forEach((formKey) => {
      if (formKey == "images") {
        formData[formKey].value = [];
        formData[formKey].invalid = false;
        formData[formKey].helperText = "";
      } else {
        formData[formKey].value = "";
        formData[formKey].invalid = false;
        formData[formKey].helperText = "";
      }
    });
    setMessage("");
    setGalleryForm(formData);
  };

  const submitHandler = (event) => {
    event.preventDefault();
    console.log("submit", galleryForm);
    let updatedForm = { ...galleryForm };
    console.log("update", updatedForm);
      console.log("final form", galleryForm);
      clearForm();
  };

  return (
    <Gallery
      {...props}
      {...{
        submitHandler,
        selectImages,
        message,
        galleryForm,
        inputChangedHandler,
      }}
    />
  );
});

export default enhancer;
import React,{useffect,useState}来自“React”;
从“redux”导入{compose};
从“/index”导入库;
从“/galleryField”导入galleryField;
导出let enhancer=compose((图库)=>({…props})=>{
const[galleryForm,setGalleryForm]=使用状态(galleryfield);
const[message,setMessage]=useState(“”);
const selectImages=(事件)=>{
const updatedForm={
…厨房式,
};
控制台日志(“检查:”,galleryForm);
对于(var i=0;i{
const updatedForm={
…厨房式,
};
console.log(updatedForm);
updatedForm[inputIdentifier].value=event.target.value;
updatedForm[inputIdentifier]。无效=false;
updatedForm[inputIdentifier].helperText=“”;
console.log(updatedForm);
集合表格({
…更新的表单,
});
控制台日志(galleryForm);
};
常量clearForm=(事件)=>{
让allFormKeys=Object.keys(galleryForm);
设formData={…galleryForm};
AllFormKey.forEach((formKey)=>{
如果(formKey==“图像”){
formData[formKey]。值=[];
formData[formKey]。无效=错误;
formData[formKey].helperText=“”;
}否则{
formData[formKey]。值=”;
formData[formKey]。无效=错误;
formData[formKey].helperText=“”;
}
});
设置消息(“”);
setGalleryForm(formData);
};
常量submitHandler=(事件)=>{
event.preventDefault();
控制台日志(“提交”,galleryForm);
让updatedForm={…galleryForm};
日志(“更新”,updatedForm);
控制台日志(“最终表格”,galleryForm);
clearForm();
};
返回(
);
});
导出默认增强器;
因此,每当我首先单击上载图像按钮时,我都会使用galleryForm的临时副本,然后在获得正确的文件后,使用selectImage按钮函数中的useState挂钩更新galleryForm

因此,我的问题是,当我最初从galleryForm的打印更新版打印galleryForm的临时副本时,即使是在功能的后期更新我的表格


与submitHandle函数面临的问题相同,clearForm函数更新galleryForm,即使我在最后调用函数,也会因此丢失表单数据,并在最初打印galleryForm后获得空表单

您正在使用spreadSyntax克隆galleryForm,但是必须注意,spread syntax只生成对象的浅拷贝。新对象中的嵌套值仍然共享引用,当您尝试更新嵌套值时,该值也会反映在原始状态中

正确的更新方法是在每个嵌套级别克隆值,如下所示

const selectImages = (event) => {
    console.log("check:", galleryForm);
    const imagesValue = [];
    for (var i = 0; i < event.target.files.length; i++) {
      if (event.target.files.item(i).name.match(/\.(jpg|jpeg|png)$/)) {
        imagesValue.push(event.target.files.item(i));
      }
    }

    // Update nested state
    setGalleryForm(prevGalleryForm => ({ 
         ...prevGalleryForm, 
         images: {
              ...prevGalleryForm.images, 
              value: prevGalleryForm.images.concat(imagesValue)
         } 
    }));
    let message = `${imagesValue.length} valid image(s) selected`;
    console.log(galleryForm);
    setMessage(message);
  };

  const inputChangedHandler = (event, inputIdentifier) => {
    const updatedForm = {
      ...galleryForm,
      [inputIdentifier]: {
         ...galleryForm[inputIdentifier],
         value: event.target.value,
         invalid: false,
         helperText:"",
      }
    };
    console.log(updatedForm);
    setGalleryForm(updatedForm);
    console.log(galleryForm);
  };

  const clearForm = (event) => {
    let allFormKeys = Object.keys(galleryForm);
    let formData = { ...galleryForm };
    allFormKeys.forEach((formKey) => {
      if (formKey == "images") {
        formData[formKey].value = [];
        formData[formKey].invalid = false;
        formData[formKey].helperText = "";
      } else {
        formData[formKey].value = "";
        formData[formKey].invalid = false;
        formData[formKey].helperText = "";
      }
    });
    setMessage("");
    setGalleryForm(formData);
  };
const selectImages=(事件)=>{
控制台日志(“检查:”,galleryForm);
常量图像值=[];
对于(var i=0;i({
…prevGalleryForm,
图像:{
…prevGalleryForm.images,
值:prevGalleryForm.images.concat(imagesValue)
} 
}));
让消息=`${imagesValue.length}选择有效图像`;
控制台日志(galleryForm);
设置消息(消息);
};
常量inputChangedHandler=(事件,inputIdentifier)=>{
const updatedForm={
…厨房式,
[输入标识符]:{
…galleryForm[inputIdentifier],
值:event.target.value,
无效:false,
helperText:“”,
}
};
console.log(updatedForm);
setGalleryForm(updatedForm);
控制台日志(galleryForm);
};
常量clearForm=(事件)=>{
让allFormKeys=Object.keys(galleryForm);
设formData={…galleryForm};
AllFormKey.forEach((formKey)=>{
如果(formKey==“图像”){