Reactjs formik удаляет элемент из массива

#javascript #reactjs #formik

#javascript #reactjs #formik

Вопрос:

У меня есть эти состояния в моем компоненте.

      const [initialValues, setInitialValues] = useState({
        name: "",
        name2: "",
        items: []
      });
  

name и name2 объединил вместе и создал массив {name: 'sss', name2: 'sss'} и отправил в items массив. Нажимная часть в порядке. Единственная проблема заключается в том, кто должен удалить элемент из этого массива.

Это мой код https://codesandbox.io/s/material-demo-forked-u2qzv?file=/demo.js:260-362

Обычные методы массива, похоже, здесь не работают.

Как мне исправить React и Formik?

Комментарии:

1. Я думаю, что с вашим текущим подходом вы столкнетесь с большим количеством проблем в будущем. Проверьте мой ответ; вы можете настроить его, чтобы получить пользовательский интерфейс, который вы имеете в виду

Ответ №1:

Я думаю FieldArray , что компонент наиболее подходит для вашего варианта использования.
Я изменил ваш пример codesandbox, чтобы использовать его:

 import React from "react";
import { Button } from "@material-ui/core";
import { Formik, Form, Field, FieldArray } from "formik";
import { TextField } from "formik-material-ui";

// Here is an example of a form with an editable list.
// Next to each input are buttons for insert and remove.
// If the list is empty, there is a button to add an item.
export default ComboBox = () => (
  <Formik
    initialValues={{
      items: [
        {
          name: "James",
          name2: "Bond"
        }
      ]
    }}
    onSubmit={(values) =>
      setTimeout(() => {
        alert(JSON.stringify(values, null, 2));
      }, 500)
    }
    render={({ values }) => (
      <Form>
        <FieldArray
          name="items"
          render={(arrayHelpers) => (
            <div>
              {values.items amp;amp; values.items.length > 0 ? (
                values.items.map((item, index) => (
                  <div key={index}>
                    <Field
                      component={TextField}
                      variant="outlined"
                      fullWidth
                      label="Name"
                      name={`items.${index}.name`}
                    />
                    <Field
                      component={TextField}
                      variant="outlined"
                      fullWidth
                      label="Name2"
                      name={`items.${index}.name2`}
                    />
                    <Button
                      type="button"
                      onClick={() => arrayHelpers.remove(index)} // remove an item from the list
                    >
                      -
                    </Button>
                    <Button
                      type="button"
                      onClick={() =>
                        arrayHelpers.insert(index, { name: "", name2: "" })
                      } // insert an empty item at a position
                    >
                       
                    </Button>
                  </div>
                ))
              ) : (
                <Button
                  type="button"
                  onClick={() => arrayHelpers.push({ name: "", name2: "" })}
                >
                  {/* show this when user has removed all items from the list */}
                  Add item
                </Button>
              )}
              <div>
                <Button type="submit">Submit</Button>
              </div>
            </div>
          )}
        />
      </Form>
    )}
  />
);
  

Комментарии:

1. FiledArrayProps — это еще один способ сделать это. У них есть функции удаления, нажатия, вставки для управления полем <Имя поля=»itemsAndServices»> {(fieldArrayProps) => { return (.. fieldArrayProps} /> ); }} </FieldArray>

Ответ №2:

Вы можете использовать функцию setValues Formik для установки значений формы

 {
  values.items.map((e, i) => (
    <div key={e.i}>
      <Button
        variant='contained'
        onClick={() => {
          setValues({
            name: '',
            name2: '',
            items: values.items.filter((newE) => newE !== e), // Remove clicked item
          })
        }}
      >
        remove {e.name}
      </Button>
    </div>
  ))
}
  

Полный фрагмент кода приведен ниже:

 /* eslint-disable no-use-before-define */
import React, { useState } from 'react'
import { Button } from '@material-ui/core'

import { Formik, Form, Field } from 'formik'
import { TextField } from 'formik-material-ui'
export default function ComboBox() {
  const [initialValues, setInitialValues] = useState({
    name: '',
    name2: '',
    items: [],
  })

  return (
    <Formik
      initialValues={initialValues}
      onSubmit={() => {}}
      enableReinitialize
    >
      {({
        isValid,
        dirty,
        values,
        handleChange,
        handleBlur,
        setFieldValue,
        setValues,
      }) => {
        return (
          <Form>
            <div>
              <Field
                name='name'
                label='Name'
                variant='outlined'
                component={TextField}
                variant='outlined'
                fullWidth
              />
              <Field
                name='name2'
                label='Name2'
                variant='outlined'
                component={TextField}
                variant='outlined'
                fullWidth
              />
            </div>

            <Button
              variant='contained'
              onClick={() => {
                console.log('values', values)
                setFieldValue(`items[${values.items.length}]`, {
                  name: values.name,
                  name2: values.name2,
                })
              }}
            >
              add item
            </Button>

            {values.items.map((e, i) => (
              <div key={e.i}>
                <Button
                  variant='contained'
                  onClick={() => {
                    setValues({
                      name: '',
                      name2: '',
                      items: values.items.filter((newE) => newE !== e), // Remove clicked item
                    })
                  }}
                >
                  remove {e.name}
                </Button>
              </div>
            ))}
          </Form>
        )
      }}
    </Formik>
  )
}

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const agents = [
  { name: 'Pathum', id: 1 },
  { name: 'Chamod', id: 2 },
  { name: 'Avishka', id: 3 },
]