反应中的对象克隆

时间:2021-04-28 02:08:52

标签: javascript reactjs object react-context context-api

我正在制作一个简单的 React 应用程序,其中包含一些基本输入,例如 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 但这是记录最新更改的值。

工作示例:

Edit React Functional Component (forked)

要求

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

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

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

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

2 个答案:

答案 0 :(得分:1)

如果你只想保持initialValue始终作为第一次值,你需要这样做

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

作为您的代码,该函数会在值发生变化时运行,因此每次值发生变化时,initialValue 都会发生变化

答案 1 :(得分: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>
  );
};

Edit object-clone-in-react