Home > Mobile >  Update an array inside an object with unique value in react with hook
Update an array inside an object with unique value in react with hook

Time:10-21

I have a two selection list from where i can select the value

list one= "A", "B"

list two = "C", "D", "E", "F"

I have a state in react const [filterTags, setFilterTags] = useState({ one: [], two: [] });

I can pass one val at a time from any of the list in updateValue(val) I need to update the filterTags in such a vay that if its val is from list one that is A or B it should update the state like this {one:["A"]: two:[]}

const updateValue = (val) => {
        if (val === 'A' || val === 'B') {
            setFilterTags({ one: val });
        } else {
            setFilterTags({ ...filterTags, two: val });
        }
    };

if I pass A C C D B A E C one by one it should update the array with the unique values and the output should be

{one:["A"]: two:[]} //passing A
{one:["A"]: two:["C"]} //passing C
{one:["A"]: two:["C"]} // same since C is already there in two on passing C
{one:["A"]: two:["C","D"]} //passing D
{one:["A","B"]: two:["C","D"]}  //passing B
{one:["A","B"]: two:["C","D"]} //same since A is already present in one on //passing A
{one:["A","B"]: two:["C","D","E"]} //passing E
{one:["A","B"]: two:["C","D","E"]}// final output on passing C

it should update the respective element with unique values right now the above code can just update a single value

CodePudding user response:

You should make sure that you are only adding elements that are not already there, you can use the includes function on the arrays to check for that, and you also want to make sure that you are keeping all the previous content.

A potential solution could be to do the following:

const updateValue = (val) => {
  if (val === 'A' || val === 'B') {
    if(!filterTags.one.includes(val)) {
      setFilterTags((prev) => ({ one: [...prev.one, val], two: prev.two }));
    }
  } else {
    if(!filterTags.two.includes(val)) {
      setFilterTags((prev) => ({ one: prev.one, two: [...prev.two, val] }));
    }
  }
};

CodePudding user response:

This commented code can help you:

const updateValue = (val) => {
  //creating a temporary copy of filterTags
  const tempFilterTags = {...filterTags}
  //checking if val is A or B and if finterTag.one does not contain the value
  if ((val === 'A' || val === 'B') && filterTags.one.find(el=> el == val) === null) {
    //if success, push the value for field one and update filterTag
    tempFilterTags.one.push(val)
    setFilterTags(tempFilterTags)
  } 
  //checking if val is C, D, E of F and if finterTag.two does not contain the value
  if ((val === 'C' || val === 'D' || val === 'E' || val === 'F') && filterTags.two.find(el=> el == val) === null) {
    //if success, push the value for field two and update filterTag
    tempFilterTags.two.push(val)
    setFilterTags(tempFilterTags)
  } 
};

CodePudding user response:

Use the functional updates option, when setting the state, to get the previous value (prev), and use spread to create a new state with the previous and updated values. Use a Set to maintain unique values.

const updateValue = (val) => {
  if (val === 'A' || val === 'B') {
    setFilterTags(prev => ({ ...prev, one: [...new Set([...prev.one, val])] }));
  } else {
    setFilterTags(prev => ({ ...prev, two: [...new Set([...prev.two, val])] }));
  }
};

How there is too much code repetition here, since the logic for setting the state is identical, and just the key changes, so you can refactor it:

const updateValue = (val) => {
  const key = val === 'A' || val === 'B' ? 'one' : 'two';
  
  setFilterTags(prev => ({ ...prev, [key]: [...new Set([...prev[key], val])] }));
};

You can also use Array.includes as suggested by Houssam to avoid updating the state:

const updateValue = (val) => {
  const key = val === 'A' || val === 'B' ? 'one' : 'two';

  setFilterTags(prev => {
    const key = val === 'A' || val === 'B' ? 'one' : 'two';
    
    return prev[key].includes(val)
      ? prev
      : { ...prev, [key]: [...prev[key], val] };
  });
};
  • Related