简体   繁体   English

如何在 React 中检查 object 数组是否存在于 state 中?

[英]How to check if array of object exist in state in React?

I'm building a dynamic form using React JS.我正在使用 React JS 构建动态表单。 in one of my form i've created an input form of 10. to get clean code i've created an object and map through it for the form.在我的一个表单中,我创建了一个 10 的输入表单。为了获得干净的代码,我通过它为表单创建了一个 object 和 map。 code is below.代码如下。

{homeAmeneties.map((home) => {
    <div className="h-8 flex justify-end  rounded-md pr-10">
                    <input
                      type="number"
                      onInput={(event) =>
                        (event.target.value = event.target.value.slice(
                          0,
                          event.target.maxLength
                        ))
                      }
                      maxLength="3"
                      onChange={(e) => updateVal(e, home.name)}
                      className="border-[1px] w-1/2  border-black rounded-md h-full focus:outline-none px-2"
                    />
                  </div>
})}

then afterwards i've created a useState([]) and used a conditional to check if the field exists, so that i can only update the value.然后我创建了一个useState([])并使用条件检查该字段是否存在,以便我只能更新该值。

const [amen, setAmen] = useState([]);
const updateVal = (e, type) => {
amen.some((item) => {
        if (item.name === type) {
          setAmen({ name: type, val: e.target.value });
        } else {
          setAmen({ name: type, val: e.target.value });
        }
      });
}

when i run this it throws an error.当我运行它时它会抛出一个错误。 amen.some is not a function error. amen.some is not a function错误。 what i want to achieve is, initially the state is empty.我想要实现的是,最初 state 是空的。 but when one field value changes it add it to the array as { name: type, val: e.target.value } .但是当一个字段值更改时,它会将其作为{ name: type, val: e.target.value }添加到数组中。 so before it's added we check if the type already exists.所以在添加之前我们检查类型是否已经存在。 if so then we change the value of that exact array of object. but if the type doesn't exist it create an new object. How can i do that?如果是这样,那么我们更改 object 的确切数组的值。但如果类型不存在,它会创建一个新的 object。我该怎么做?

It looks like the error is being thrown because amen is an array, but you're trying to use the.some() method on it, which is a method of the Array prototype, but it's not a function. .some() returns a boolean and not an Array, so you can't chain other Array methods to it.看起来错误被抛出是因为 amen 是一个数组,但你试图在它上面使用 .some() 方法,这是 Array 原型的一个方法,但它不是 function。.some() 返回boolean 而不是数组,因此您不能将其他数组方法链接到它。

To achieve what you want, you can use the.findIndex() method instead.要实现您想要的效果,您可以改用 .findIndex() 方法。 This method returns the index of the first element in the array that satisfies the provided testing function, or -1 if none is found.此方法返回数组中满足提供的测试 function 的第一个元素的索引,如果未找到,则返回 -1。

Here's an example of how you can update the state using the.findIndex() method:以下是如何使用 .findIndex() 方法更新 state 的示例:

      const updateVal = (e, type) => {
      const index = amen.findIndex((item) => item.name === type);
    
      if (index !== -1) {
        const newAmen = [...amen];
        newAmen[index] = { name: type, val: e.target.value };
        setAmen(newAmen);
      } else {
        setAmen([...amen, { name: type, val: e.target.value }]);
      }
    };

This code first finds the index of the object in the amen array that has the matching name property to the type passed in. If the index is not -1, it means that the object already exists in the array, so it creates a new array (newAmen) that is a copy of the current state array, updates the value of the object at the index, and sets the new array as the new state. If the index is -1, it means that the object doesn't exist in the array, so it creates a new array that includes the new object, and sets that as the new state.这段代码首先在amen数组中找到object的索引,该索引的name属性与传入的类型匹配。如果索引不为-1,则表示object已经存在于数组中,因此创建一个新数组(newAmen) 即当前state数组的副本,更新索引处object的值,并将新数组设置为新的state。如果索引为-1,则表示object不存在数组,因此它会创建一个新数组,其中包含新的 object,并将其设置为新的 state。

Also, in your code, you're trying to set state with object and that's not how state works.此外,在您的代码中,您试图将 state 设置为 object,而这不是 state 的工作方式。 In your case, you're trying to set state with an object, but it's expecting an array, that's why it's throwing an error.在您的情况下,您尝试将 state 设置为 object,但它需要一个数组,这就是它抛出错误的原因。

You should use setAmen(prevAmen => [...prevAmen, { name: type, val: e.target.value }]);你应该使用setAmen(prevAmen => [...prevAmen, { name: type, val: e.target.value }]);

      const updateVal = (e, type) => {
      const index = amen.findIndex((item) => item.name === type);

      if (index !== -1) {
        setAmen((prevAmen) => {
          prevAmen[index] = { name: type, val: e.target.value };
          return [...prevAmen];
        });

      } else {
        setAmen((prevAmen) => [...prevAmen, { name: type, val: e.target.value }]);

      }
    };

This way it should work as expected.这样它应该按预期工作。

I have 3 things to point out:我有3点要指出:

  • You said you created an object and map through it to render the input fields.你说你通过它创建了一个 object 和map来呈现输入字段。 Actually, you can only map over arrays in JavaScript .实际上,你只能在JavaScriptmap超过arrays
  • In your updateVal method call, you are setting the react state to an object instead of an array .在您的updateVal方法调用中,您将react state设置为object而不是array
  • I wouldn't recommend using Array.some () to update the state. Instead, I would use Array.findIndex () .我不建议使用Array.some ()来更新 state。相反,我会使用Array.findIndex ()

Solution解决方案

const updateVal = (e, type) => {
  const updatedAmen = [ ...amen ]; // create a new array to avoid mutating the state directly

  // check if an input already exists with the said type & get the index position
  const exisitingAmenIdx = updatedAmen.findIndex((a) => a.name === type);

  if (exisitingAmenIdx >= 0) {
    updatedAmen[exisitingAmenIdx].val = e.target.value;
  } else {
    updatedAmen.push({
      name: type,
      val: e.target.value
    })

    // finally update the state
    setAmen(updatedAmen)
  }
};

It's because you're setting the state value of amen to be the object you're aiming to append to the array:这是因为您将amen的 state 值设置为 object,您的目标是 append 到数组:

  setAmen({ name: type, val: e.target.value });

  // amen = { name: type, val: e.target.value }

Since it changes from being an Array , Array.some() is not going to be defined.由于它从 Array 变为Array ,因此不会定义Array.some() One way you can go about this is:您可以拨打 go 的一种方法是:

  setAmen([{ name: type, val: e.target.value }, ...amen]);

Create a new Array so react will update the state. Add the new element, and then use the spread operator ...amen to extract the other elements.创建一个新数组,因此 React 将更新 state。添加新元素,然后使用扩展运算符...amen提取其他元素。

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

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