Home > OS >  Update an array inside array of object on the basis of unique and repeated values
Update an array inside array of object on the basis of unique and repeated values

Time:10-26

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 {first:["A"]: second:[]} ,

If I pass the same value again it should delete the value and update it kind of checking and unchecking

the below code can add new values if they are not present but if they are present it does nothing .. it should remove the value if they are present

  const updateValue = (val) => {
        setFilterTags((prev) => {
            const key = val === 'A' || val === 'B' ? 'first' : 'second';
            return prev[key].includes(val)
                ? prev
                : { ...prev, [key]: [...prev[key], val] };
        });
    };

few usecase are

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

{first:["A"]: second[]} //passing A
{first:["A"]: second["C"]} //passing C
{first:["A"]: second:[]} // same since C is already there it removes and update 
{first:["A"]: second["D"]} //passing D
{first:["A","B"]: second:["D"]}  //passing B
{first:["B"]: second:["D"]} //same since A is already present it removes "A" on passing A
{first:["B"]: second:["D","E"]} //passing E
{first:["B"]: second:["D","E","C"]}// final output on passing C

it should update the respective element with unique values if not present and delete the values if present right now the above code can just update a the unique values

CodePudding user response:

The reason your code isn't working is you're missing a filter() that removes the value. You can use a simple helper function toggleVal() that performs the toggle logic including the filter() then returns the updated list.

const oneVals = ["A", "B"];
const twoVals = ["C", "D", "E", "F"];

const [filterTags, setFilterTags] = useState({ one: [], two: [] });

const toggleVal = (possibleVals, list, value) => {
  if (!possibleVals.includes(value)) {
    return list;
  }
  return list.includes(value)
    ? list.filter(val => val !== value)
    : [...list, value];
};

const updateValue = (value) => {
  setFilterTags(({ one, two }) => ({
    one: toggleVal(oneVals, one, value),
    two: toggleVal(twoVals, two, value)
  }));
};

Live Demo

CodePudding user response:

I made some changes to your code - instead of using a ternary operator which is confusing in more complex situations I opted for an if statement.

I cleaned up the key selector.

The way you delete values from an object (which an secretly is) is you write delete followed by a reference to the key you desire to remove.

  const updateValue = (val) => {
    setFilterTags((prev) => {


      const key = ['A', 'B'].includes(val) ? 'first' : 'second';

      if (prev[key].includes(val)) {
        // clone the current key you are using because don't mutate state.
        let prevClone = {
          ...prev[key]
        }
                    // delete the desired key
        delete prevClone[prevClone.indexOf(val)]
        // return the whole state, with the mutation.
        return {
          ...prev,
          [key]: prevClone
        }
      } else {
        // else just add it.
        return {
          ...prev,
          [key]: [...prev[key], val]
        };
      }

    });
  };
  • Related