确定在Formik FieldArray中已删除(创建和修改)了哪些项目 [英] Identifying what item have been deleted (created and modifed) in a Formik FieldArray

查看:88
本文介绍了确定在Formik FieldArray中已删除(创建和修改)了哪些项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想知道Formik是否具有本机解决方案来识别形式为FieldArray的添加和删除(和更新)吗?

Was wondering if Formik has a native solution for identifying the addition and deletion (and update) of FieldArray in the form ?

我在这里的沙箱上有代码 https://codesandbox.io/s/jn7x2m75o9 (基于原始Formik数组示例@ https://github.com/jaredpalmer/formik/blob/master/examples/Arrays.js )

I have the code on sandbox here https://codesandbox.io/s/jn7x2m75o9 ( based on the original Formik Array example @ https://github.com/jaredpalmer/formik/blob/master/examples/Arrays.js )

还有这里的相关部分:

定义了最初的 3个朋友state,我怎么能在我的onSubmithandler中知道已被修改,删除,更新的一个.

With an Initial state of 3 friend defined, how can I know in my onSubmithandler which one were modified,deleted,updated.

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;

因此,如果与上述用户一起在哪里:

So if with the above a user where to :

  1. 点击Friend_A下面的X
  2. 将Friend_C电子邮件修改为email_C@nothere.com
  3. 点击添加朋友"
  4. 输入值名称:New_Friend_X,电子邮件:XX@YY.com
  5. 点击添加朋友"
  6. 输入值名称:New_Friend_Z和电子邮件:Friend_Z@coolplace.com
  7. 点击新输入的"New_Friend_X"下方的"X"按钮
  8. 点击邀请"

在我的mySubmit中,我正在寻找一种轻松获取的方式:

in my mySubmit I'm looking for a way to easily get :

  1. Friend_A已被删除
  2. Friend_C已修改
  3. 添加了New_Friend_Z(不在formik的原始InitialValues中)

(我不在乎New_Friend_X.不需要知道它是否已添加/删除)

(I Don't care about New_Friend_X. No need to know it was added/removed )

这是为了最大程度地减少对后端的REST调用,以创建/更新实体/链接,而且我真的不想在调用<之前在删除按钮的onClick处理程序中编写自己的辅助状态". Formik 提供的c4>处理程序,以跟踪需要从数据库中删除的内容.

Point of this is to minimize rest call to the back end to create/update entity/link and also I really dont want to write my own "secondary state" in the onClick handler of the remove button before calling the remove(index) handler provided by Formik to track what need to be deleted from the DB.

推荐答案

它不是Formik内置的,但是用javascript并不难.

Its not built into Formik, but it is not hard to do in javascript.

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

First, understand that Formik clones the object you give to initialValues. So in onSubmit, you will compare the final value to your original object.

传入数据:

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声明:

Modified Formik declaration:

<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);
  }}
  ...

助手功能:

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 };
};

代码框内的代码

注意:如果更改朋友的名字,它将显示为原始朋友的删除和新朋友的 add 朋友.
一个更可靠的解决方案是向每个朋友添加一个(隐藏的)"id"字段.然后,不比较名称,而是比较 id .
这需要在添加每个朋友时生成一个新的ID.

NOTE: If you change the name of a friend, that will appear as a delete of original friend and an add of a new friend.
A more robust solution would be to add a (hidden) "id" field to each friend. Then instead of comparing name, would compare id.
That requires generating a new id as add each friend.

这篇关于确定在Formik FieldArray中已删除(创建和修改)了哪些项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆