简体   繁体   English

使用 delete() 从数组中删除 object,并在 TextField 中呈现对象名称

[英]Using delete() to remove object from array, and render the objects name in a TextField

I have a component which facilitates entering a data object to an array of objects via submitting the data into a TextField.我有一个组件,它有助于通过将数据提交到 TextField 来将数据 object 输入到对象数组中。 Upon entering an ingredient, an AddIcon and RemoveIcon will show up on either side of the TextField so you can add or remove ingredients as needed.输入成分后,一个 AddIcon 和 RemoveIcon 将显示在 TextField 的任一侧,因此您可以根据需要添加或删除成分。 Entering the data works, and upon entering the data each object is given an id which is associated with the it's id in the array.输入数据有效,在输入数据后,每个 object 都会被赋予一个与数组中的 id 相关联的 id。 Adding everything works, however, upon removal of an item I find that the incorrect values are displayed in the TextFields.但是,添加所有内容后,在删除项目后,我发现 TextFields 中显示了不正确的值。 I'm sure the issue has something to do with how I'm rendering the value of the TextField, but I feel like I need a new pair of eyes on the problem.我确信这个问题与我如何呈现 TextField 的值有关,但我觉得我需要一双新的眼睛来解决这个问题。 I've attempted to use both delete() and array.splice().我尝试同时使用 delete() 和 array.splice()。 Here's the code这是代码

function MinusButton({ props }) {
  const { 
    id, 
    inputs, 
    setInputs,
    spiritObject,
    setSpiritObject,
    ingredientsArray,
    setIngredientsArray
  } = props;
  
  const removeInput = (e, id) => {
    const tmpInput = [...inputs]
    delete(tmpInput[id])            // this removes the correct object from the array but obviously fails eventually since it doesn't reindex
    // tmpInput.splice(id, 1)       // this technically works as well, but rendering the values does not
    setInputs(tmpInput);
  }

  return (
    <div>
      {
        inputs.length > 1 ?
          <IconButton
            id={id}
            color="primary"
            onClick={(e) => removeInput(e, id)}
          >
            <RemoveIcon fontSize="large"/>
          </IconButton>
        : false
      }
    </div>
  );
}

function PlusButton({ props }) {
  const { 
    id, 
    inputs, 
    setInputs, 
    assignId,
    spiritObject, 
    setSpiritObject, 
    ingredientsArray, 
    setIngredientsArray 
  } = props;

  const addIngredientToArray = () => {
    inputs[id] = { id: id, ...spiritObject}
    setIngredientsArray([...ingredientsArray, inputs[id]])
    setInputs([...inputs, {}])
    setSpiritObject({})
  }

  return (
    <div>
      {
        inputs.length === id+1 ? 
          <IconButton
            color="primary"
            onClick={() => addIngredientToArray()}
          >
            <AddBoxIcon fontSize="large"/>
          </IconButton>
        : false
      }
    </div>
  )
}
  
export default function Ingredients() {
  const classes = useStyles();
  const cocktail = useCocktail();
  const { register, handleSubmit } = useForm();
  const [spiritObject, setSpiritObject] = useState({});
  const [ingredientsArray, setIngredientsArray] = useState([]);
  const [inputs, setInputs] = useState([{}]);

  const onSubmit = () => {
    cocktail.addIngredients(ingredientsArray)
  }

  const onChangeInput = (e) => {
    setSpiritObject({...spiritObject, [e.target.name]: e.target.value})
  }

  return (
    <form 
      noValidate 
      className={classes.formContainer}
      id='ingredients'
      name='ingredients'
      onSubmit={handleSubmit(onSubmit)} 
    >
      {
        inputs.map((input, id) => { 
          const inputProps = { 
            id, 
            inputs, 
            setInputs, 
            spiritObject, 
            setSpiritObject, 
            ingredientsArray, 
            setIngredientsArray 
          }

          return (
            <div>
              <Grid container alignContent="center" alignItems="center">
                <MinusButton props={inputProps} />
                <TextField 
                  {...register('name')}
                  id={id}
                  label='Ingredient'
                  value={inputs[id].name}
                  variant='outlined'
                  margin='normal'
                  InputProps={{className: classes.input}}
                  onChange={(e) => onChangeInput(e)}
                />
                <FormControl variant="outlined" className={classes.formControl}>
                  <Select 
                    {...register('type')}
                    defaultValue="" 
                    id="spiritType"
                    onChange={(e) => onChangeInput(e)}
                  >
                    <ListSubheader>Ingredient Type</ListSubheader>
                    {
                      types.map((type, id) => {
                        return <MenuItem key={id} value={type}>{type}</MenuItem>
                      })
                    }
                  </Select>
                </FormControl>
                <PlusButton props={inputProps} />
              </Grid>
            </div>
          )
        })
      }
    </form>
  );
}

I'm sure the solution is obvious, but I cannot see it.我确信解决方案很明显,但我看不到它。 Thank you for reading.感谢您的阅读。

delete is for fields in objects. delete用于对象中的字段。 To remove an entry from an array use filter() .要从数组中删除条目,请使用filter()

const tmpInput = [...inputs].filter(element => element.id !== id);

Try to control all your input state into the parent component.尝试将所有输入 state 控制到父组件中。 handles functions should be side-by-side with your state. handles函数应该与您的 state 并排。 Something like this:像这样的东西:

import React, { useState } from "react";
import DeleteForeverIcon from "@material-ui/icons/DeleteForever";
import AddBoxIcon from "@material-ui/icons/AddBox";
import { v4 as uuidv4 } from "uuid";

const RemoveButton = ({ onClick }) => (
  <DeleteForeverIcon
    fontSize="large"
    onClick={onClick}
    style={{ cursor: "pointer" }}
  />
);
const AddButton = ({ onClick }) => (
  <AddBoxIcon
    fontSize="large"
    onClick={onClick}
    style={{ cursor: "pointer" }}
  />
);

const InputField = ({ id, onClick }) => {
  return (
    <div>
      <input id={id} />
      <RemoveButton onClick={onClick} />
    </div>
  );
};

const App = () => {
  const [inputs, setInputs] = useState([]);

  const handleRemoveInput = (id) => {
    console.log(id);
    console.log(inputs.findIndex((input) => input.id === id));
    setInputs(inputs.filter((input) => input.id !== id));
  };
  const handleAddInput = () => {
    console.log("asd");
    setInputs([...inputs, { id: uuidv4() }]);
  };

  return (
    <div>
      <AddButton onClick={handleAddInput} />
      {inputs.map(({ id }) => {
        return (
          <InputField id={id} key={id} onClick={() => handleRemoveInput(id)} />
        );
      })}
    </div>
  );
};

export default App;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM