【问题标题】:Object clone in react反应中的对象克隆
【发布时间】:2025-11-29 00:00:02
【问题描述】:

我正在制作一个简单的反应应用程序,其中包含一些基本输入,例如 first namelast name 等,

输入的状态在上下文 api 中处理,例如,

context.js

import React, { useState } from "react";

export const FormContext = React.createContext();

export function FormProvider({ children }) {
  const [formValue, setFormValue] = useState({
    basicDetails: {
      firstName: "",
      lastName: "",
      address: {
        city: "",
        zip: ""
      }
    }
  });

  return (
    <FormContext.Provider value={[formValue, setFormValue]}>
      {children}
    </FormContext.Provider>
  );
}

在获取上下文的基本细节组件中,

  const [value, setValue] = React.useContext(FormContext);
  const { basicDetails } = value;

为了复制上下文的初始值,我尝试过使用扩展运算符,例如,

  const initialValue = { ...value };

handleSubmit 函数中尝试获取最初复制的值(即)initialValue,但这是记录最新更改的值。

工作示例:

要求

单击表单提交时,我需要使用初始上下文数据重置表单值。

为了实现将值重置为初始数据,我尝试了传播运算符{ ...value },但我认为我的方法有误。

即使JSON.parse(JSON.stringify(value)) 在这种情况下也不起作用..

请任何人帮助我在提交时将表单值设置为初始上下文。

【问题讨论】:

    标签: javascript reactjs object react-context


    【解决方案1】:

    这里的其他答案似乎就足够了。您还可以将初始字段值保存在 React ref (const initialValue = React.useRef(value);) 中,稍后以 initialValue.current 访问。

    实际上,您希望您的上下文能够更好地控制上下文状态。我建议创建一个reset 函数以包含在儿童可以使用的上下文中。

    context.js

    分解初始状态定义,提供默认上下文值,并将状态和回调传递给上下文值。

    const initialFormState = {
      basicDetails: {
        firstName: "",
        lastName: "",
        address: {
          city: "",
          zip: "123"
        }
      }
    };
    
    export const FormContext = React.createContext({
      formValue: initialFormState,
      setFormValue: () => {},
      reset: () => {}
    });
    
    export function FormProvider({ children }) {
      const [formValue, setFormValue] = useState(initialFormState);
    
      const reset = () => setFormValue(initialFormState);
    
      return (
        <FormContext.Provider
          value={{ value: formValue, setValue: setFormValue, reset }}
        >
          {children}
        </FormContext.Provider>
      );
    }
    

    basicDetails.js

    使用并解构上下文值。将提交按钮更改为type="submit",以便您可以提交表单,并在提交处理程序中调用reset 以重置表单状态。

    const BasicDetails = () => {
      const {value, setValue, reset} = React.useContext(FormContext);
      const { basicDetails } = value;
    
      const handleInputChange = (event) => {
        const { name, value: val } = event.target;
        setValue((prev) => {
          const basicDetails = {
            ...prev.basicDetails,
            ...(value.basicDetails[name] !== undefined
              ? { [name]: val }
              : { address: { ...value.basicDetails.address, [name]: val } })
          };
          return { ...prev, basicDetails };
        });
      };
    
      const handleSubmit = (e) => {
        e.preventDefault();
    
        // Do what you need with the current form values
        console.log("Values", value);
    
        // Finally reset the form
        e.target.reset();
      };
    
      return (
        <div>
          <h1> Basic Details </h1>
          <form onSubmit={handleSubmit} onReset={reset}>
            <label htmlFor="firstName">First Name: </label>
            <input
              type="text"
              className="form-control"
              id="firstName"
              name="firstName"
              value={basicDetails.firstName}
              onChange={handleInputChange}
            />
            <br />
            <br />
            <label htmlFor="lastName">Last Name: </label>
            <input
              type="text"
              className="form-control"
              id="lastName"
              name="lastName"
              value={basicDetails.lastName}
              onChange={handleInputChange}
            />
            <br />
            <br />
            <label htmlFor="lastName">City: </label>
            <input
              type="text"
              id="city"
              name="city"
              value={basicDetails.address.city}
              onChange={handleInputChange}
            />
            <br />
            <br />
            <label htmlFor="lastName">Zip: </label>
            <input
              type="text"
              className="form-control"
              id="lastName"
              name="zip"
              value={basicDetails.address.zip}
              onChange={handleInputChange}
            />
            <br />
            <br />
            <button type="submit">
              Submit
            </button>
          </form>
        </div>
      );
    };
    

    【讨论】:

    • 谢谢你的回答兄弟..我对这个问题有一个疑问,*.com/q/67265409/13270726..有没有办法在handleInputChange函数中更改这行代码{ address: { ...value.basicDetails.address, [name]: val } }),因为有时我会有更多像address 这样的对象,那么有没有一种方法可以在不对数据进行硬编码的情况下进行处理?
    • @Undefined 理想情况下,您希望表单数据是平坦的。你的状态不是,所以从嵌套到扁平(或反之亦然)的“映射”必然发生在setValue 函数中。您可以将其抽象为一个可以解析对象路径的实用程序,该实用程序可以将name="basicDetails.address.city" 解析为您需要更新的嵌套状态。请参阅 lodash object set 了解我所描述的内容。
    • 好的,兄弟,谢谢你的评论,会处理的..
    【解决方案2】:

    如果您只想将初始值始终作为第一次值,您需要这样做

    const initialValue = useMemo(() => value, []);
    

    作为您的代码,该函数在值更改时运行,因此每次值更改时initialValue都会更改

    【讨论】:

      最近更新 更多