簡體   English   中英

使用 delete() 從數組中刪除 object,並在 TextField 中呈現對象名稱

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

我有一個組件,它有助於通過將數據提交到 TextField 來將數據 object 輸入到對象數組中。 輸入成分后,一個 AddIcon 和 RemoveIcon 將顯示在 TextField 的任一側,因此您可以根據需要添加或刪除成分。 輸入數據有效,在輸入數據后,每個 object 都會被賦予一個與數組中的 id 相關聯的 id。 但是,添加所有內容后,在刪除項目后,我發現 TextFields 中顯示了不正確的值。 我確信這個問題與我如何呈現 TextField 的值有關,但我覺得我需要一雙新的眼睛來解決這個問題。 我嘗試同時使用 delete() 和 array.splice()。 這是代碼

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

我確信解決方案很明顯,但我看不到它。 感謝您的閱讀。

delete用於對象中的字段。 要從數組中刪除條目,請使用filter()

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

嘗試將所有輸入 state 控制到父組件中。 handles函數應該與您的 state 並排。 像這樣的東西:

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