Javascript 识别在Formik FieldArray中已删除(创建和修改)的项目

Javascript 识别在Formik FieldArray中已删除(创建和修改)的项目,javascript,reactjs,formik,Javascript,Reactjs,Formik,想知道Formik是否有一个本机解决方案来识别表单中FieldArray的添加和删除(以及更新) 我这里有沙盒上的代码(基于原始的Formik数组示例@) 还有这里的相关部分: 定义了3个朋友的初始状态,我如何在我的onSubmithandler中知道哪一个被修改、删除、更新 import React from "react"; import { Formik, Field, Form, ErrorMessage, FieldArray } from "formik"; const initi

想知道Formik是否有一个本机解决方案来识别表单中
FieldArray
的添加和删除(以及更新)

我这里有沙盒上的代码(基于原始的Formik数组示例@)

还有这里的相关部分:

定义了3个朋友的初始
状态
,我如何在我的
onSubmithandler
中知道哪一个被修改、删除、更新

import React from "react";
import { Formik, Field, Form, ErrorMessage, FieldArray } from "formik";

const initialValues = {
  friends: [
    {
      name: "Friend_A",
      email: "email_A@somewhere.com"
    },
    {
      name: "Friend_B",
      email: "email_B@somewhere.com"
    },
    {
      name: "Friend_C",
      email: "email_C@somewhere.com"
    }
  ]
};

const mySubmit = values => console.log();

const SignIn = () => (
  <div>
    <h1>Invite friends</h1>
    <Formik
      initialValues={initialValues}
      onSubmit={values => {
        var itemRemoved = values.GetItemRemoveFromArray; // This is what I'm looking for
        console.log(itemRemoved);
        // Would print Friend_A

        var itemAdded = values.GetItemAddedFromArray; // This is what I'm looking for
        console.log(itemAdded);
        // Would print New_Friend

        var itemUpdated = values.GetItemUpdatedInArray; // This is what I'm looking for
        console.log(itemUpdated);
        // Would print Friend_C

        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
        }, 500);
      }}
      render={({ values }) => (
        <Form>
          <FieldArray
            name="friends"
            render={({ insert, remove, push }) => (
              <div>
                {values.friends.length > 0 &&
                  values.friends.map((friend, index) => (
                    <div className="row" key={index}>
                      <div className="col">
                        <label htmlFor={`friends.${index}.name`}>Name</label>
                        <Field
                          name={`friends.${index}.name`}
                          placeholder="Jane Doe"
                          type="text"
                        />
                        <ErrorMessage
                          name={`friends.${index}.name`}
                          component="div"
                          className="field-error"
                        />
                      </div>
                      <div className="col">
                        <label htmlFor={`friends.${index}.email`}>Email</label>
                        <Field
                          name={`friends.${index}.email`}
                          placeholder="jane@acme.com"
                          type="email"
                        />
                        <ErrorMessage
                          name={`friends.${index}.name`}
                          component="div"
                          className="field-error"
                        />
                      </div>
                      <div className="col">
                        <button
                          type="button"
                          className="secondary"
                          onClick={() => remove(index)}
                        >
                          X
                        </button>
                      </div>
                    </div>
                  ))}
                <button
                  type="button"
                  className="secondary"
                  onClick={() => push({ name: "", email: "" })}
                >
                  Add Friend
                </button>
              </div>
            )}
          />
          <button type="submit">Invite</button>
        </Form>
      )}
    />
  </div>
);

export default SignIn;
从“React”导入React;
从“Formik”导入{Formik,Field,Form,ErrorMessage,FieldArray};
常量初始值={
朋友们:[
{
姓名:“朋友A”,
电子邮件:“电子邮件_A@somewhere.com"
},
{
姓名:“朋友”,
电子邮件:“电子邮件_B@somewhere.com"
},
{
姓名:“朋友”,
电子邮件:“电子邮件_C@somewhere.com"
}
]
};
const mySubmit=values=>console.log();
常量符号=()=>(
邀请朋友
{
var itemRemoved=values.GetItemRemoveFromArray;//这就是我要找的
console.log(itemRemoved);
//我会把你的朋友打印出来吗
var itemAdded=values.GetItemAddedFromArray;//这就是我要找的
console.log(itemsadded);
//我会把新朋友打印出来
var itemUpdated=values.GetItemUpdatedInArray;//这就是我要找的
console.log(项目更新);
//我会打印Friend_C
设置超时(()=>{
警报(JSON.stringify(值,null,2));
}, 500);
}}
render={({values})=>(
(
{values.friends.length>0&&
values.friends.map((friends,index)=>(
名称
电子邮件
删除(索引)}
>
X
))}
推送({name:,email:})}
>
加朋友
)}
/>
邀请
)}
/>
);
导出默认签名;
因此,如果与上述用户一起,您可以选择:

  • 点击下面的X键
  • 将朋友的电子邮件修改为电子邮件_C@nothere.com
  • 单击“添加朋友”
  • 输入值名称:新朋友和电子邮件:XX@YY.com
  • 单击“添加朋友”
  • 输入值名称:New_Friend_Z和电子邮件:Friend_Z@coolplace.com
  • 单击新输入的“新朋友”下方的“X”按钮
  • 单击“邀请”
  • 在我的问题中,我正在寻找一种容易获得:

  • 朋友A被移除了
  • Friend_C被修改了
  • 添加了新的_Friend_Z(不在formik的原始初始值中)
  • (我不关心新朋友。不需要知道它已被添加/删除)


    这一点是为了尽量减少对后端的rest调用,以创建/更新实体/链接,而且在调用
    remove(索引)之前,我真的不想在remove按钮的
    onClick
    处理程序中编写我自己的“次要状态”
    处理程序由Formik提供,用于跟踪需要从数据库中删除的内容。

    它没有内置在Formik中,但在javascript中并不难做到

    首先,要了解Formik克隆了您提供给
    initialValues
    的对象。因此,在
    onSubmit
    中,将最终值与原始对象进行比较

    传入数据:

    const initialFriends = [
      {
        name: "Friend_A",
        email: "email_A@somewhere.com"
      },
      {
        name: "Friend_B",
        email: "email_B@somewhere.com"
      },
      {
        name: "Friend_C",
        email: "email_C@somewhere.com"
      }
    ];
    
    const initialValues = { friends: initialFriends };
    
    修改的Formik声明:

    <Formik initialValues={initialValues}
      ...
      onSubmit={values => {
        const { added, deleted, changed } = addDeleteChange(
          initialFriends,
          values.friends
        );
    
        setTimeout(() => {
          alert(
            "Added: " + JSON.stringify(Object.fromEntries(added.entries()))
          );
          alert(
            "Deleted: " + JSON.stringify(Object.fromEntries(deleted.entries()))
          );
          alert(
            "Changed:" + JSON.stringify(Object.fromEntries(changed.entries()))
          );
          alert(JSON.stringify(values, null, 2));
        }, 500);
      }}
      ...
    


    注意:如果您更改朋友的姓名,则会显示为删除原始朋友和添加新朋友。
    一个更健壮的解决方案是为每个朋友添加一个(隐藏的)“id”字段。然后将比较id,而不是比较名称。
    这需要在添加每个朋友时生成一个新id

    function partition(array, filter) {
      let pass = [],
        fail = [];
      array.forEach(e => (filter(e) ? pass : fail).push(e));
      return [pass, fail];
    }
    
    const addDeleteChange = (in1, out1) => {
      let inMap = new Map(in1.map(f => [f.name, f]));
      let outMap = new Map(out1.map(f => [f.name, f]));
      let inNames = new Set(inMap.keys());
      let outNames = new Set(outMap.keys());
      let [kept, added] = partition(out1, f => inNames.has(f.name));
      let deleted = in1.filter(f => !outNames.has(f.name));
      //alert(JSON.stringify(Object.fromEntries(deleted.entries())));
      let changed = kept.filter(f => f.email !== inMap.get(f.name).email);
      //alert(JSON.stringify(Object.fromEntries(changed.entries())));
      return { added: added, deleted: deleted, changed: changed };
    };