简体   繁体   English

从组件内的表单中删除值

[英]remove value from form within component

I am trying to let users remove values from there current settings.我试图让用户从当前设置中删除值。

I have a series of values users can have for there settings that are displayed in a pill format that they can click X on to delete, ie,我有一系列用户可以拥有的设置值,这些值以药丸格式显示,他们可以单击 X 删除,即,

export default function Pill({ value, handleChange }) {

  // const [times, setTimes] = useState([]);

    return (
      <div className="bg-gray-600 text-white text-xs px-2 py-0.5 w-max-content rounded-lg align-middle mr-1 mb-1">
        {value}
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="16"
          height="16"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
          className="inline-block align-middle cursor-pointer"
          onClick={() => handleChange(value, "remove")}
        >
          <line x1="18" y1="6" x2="6" y2="18" />
          <line x1="6" y1="6" x2="18" y2="18" />
        </svg>
      </div>
    );
  }

This is used as a component as below,这用作如下组件,

{substanceDetails &&
              substanceDetails.map((subst) => (
                <Pill
                  registerInput={register}
                  optionLabel="substance"
                  value={subst.substance}
                  key={subst.substance}
                  optionName="substance"
                  allOptions={["Dexamphetamine", "Ritalin"]}
                  handleChange={handleChange}
                />
              ))}

Given the handle change, which needs to be changed, but it would look something like this,鉴于需要更改的句柄更改,但它看起来像这样,

const handleChange = (value, mode) => {
    let updatedValues = values;
    if (mode === 'remove') {
      updatedValues = values.filter((elem) => elem !== value);
    } else if (!updatedValues.includes(value)) updatedValues = [...values, value];
    setValues(updatedvalues);
  };

Mutation issue突变问题

You are mutating state in your handleChange function:您正在修改handleChange函数中的状态:

const handleChange = (value, mode) => {
    let updatedValues = values; //takes the reference to state variable
    if (mode === 'remove') {
      updatedValues = values.filter((elem) => elem !== value); //mutation
    } else if (!updatedValues.includes(value)) updatedValues = [...values, value];
    setValues(updatedvalues);
  };

You can use something like this:你可以使用这样的东西:

const handleChange = (value, mode) => {
    if(mode==="remove") setValues(vals => vals.includes(value) ? vals.filter(v => v !== value) : [...vals, value])
  };

If it is an array of objects:如果是对象数组:

.includes() won't work as expected if your array elements are not primitive values.如果您的数组元素不是原始值, .includes()将不会按预期工作。 You can use .find() or .some() in that case:在这种情况下,您可以使用.find().some()

Example of filtering by the field duration for simplicity :为简单起见,按字段duration过滤的示例

const handleChange = (value, mode) => {
    if(mode==="remove") setValues(vals => vals.find(v=> v.duration === value.duration) ? vals.filter(v => v.duration !== value.duration) : [...vals, value])
  };

after reading your code, I found the main problem might not be the mutation issue, but you didn't manage the state very well.阅读您的代码后,我发现主要问题可能不是突变问题,而是您没有很好地管理状态。

First, your substanceDetails should be stored in YourSubstanceListComponent component, not in your Pill component, something like this.首先,您的substanceDetails应该存储在YourSubstanceListComponent组件中,而不是存储在您的Pill组件中,就像这样。 This is the main reason why your first approach does not work .这是您的第一种方法不起作用的主要原因

// in YourSubstanceListComponent
const YourSubstanceListComponent = () = {
  const [values, setValues] = useState([]);
  const handleChange = (value, mode,optionName) => {
    // Should call `setValues` in this function
    const newValues = [];// TODO
    setValues(newValues);
  }

  return (
    <>
      {values.map(v => <Pill {...otherPillProps} value={v.substance} />)}
    </>
  )
}

Then, your handleChange should be placed in YourSubstanceListComponent .然后,您的handleChange应该放在YourSubstanceListComponent The reason why is you might don't want to pass setValues to your Pill component.原因是您可能不想将setValues传递给您的Pill组件。

Next is the part about getting new removed values items.接下来是关于获取新的删除值项目的部分。 According the docs:根据文档:

They don't modify the original array.他们不会修改原始数组。 So you can use them like in your code and it should work.所以你可以像在你的代码中一样使用它们,它应该可以工作。

But, I found some more problems in your code and I think you should check it again.但是,我在您的代码中发现了更多问题,我认为您应该再次检查。

  • Array.reduce will return your array to a single value. Array.reduce会将您的数组返回到单个值。 I saw that you used it to get a new array from an array.我看到您使用它从数组中获取新数组。 It makes no sense since you can use map (when the number of elements does not change) or filter (when the number of elements will change).这是没有意义的,因为您可以使用map (当元素数量不变时)或filter (当元素数量发生变化时)。 I rarely use any other methods apart from map and filter in all my life.除了mapfilter ,我这辈子很少使用任何其他方法。
  • In your updated handleChange function, I don't see the optionName variable.在您更新的handleChange函数中,我没有看到optionName变量。 Where does it come from?它从何而来? Maybe you didn't update your Pill component.也许你没有更新你的Pill组件。

@ShinaBR2 @ShinaBR2

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

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