3

I am using useSelector() to get state and when I apply some filter to local state variable, my global state is mutating. Not sure why. Below is the code.

const filterVacations = (employees, status) => {
    if(status === 'Approved') {
        employees.forEach(item => {
            item.vacations = item.vacations.filter(vac => vac.approved === true);

        });
    }
    else if(status === 'Unapproved') {
        employees.forEach(item => {
            item.vacations = item.vacations.filter(vac => vac.approved === false);

    });

    }
    return employees.filter(item => item.vacations.length > 0);
  }

and calling this function as below:

const Vacations = () => {
    const state = useSelector((state:State) => state);
    const view = state.view;
    const filter = state.filter;
    const employees = state.employees;

    employees = filterVacations(employees, filter); 

    return (
      <>
      //some component...
      </>);

  }

why is state is mutating here?

Kuldeep Bora
  • 4,072
  • 3
  • 12
  • 16

2 Answers2

2

Its because you are not passing value when you say const filter = state.filter; but its passing reference.

For example, consider a Bookshelf having JS book on top of it in a Library. When you visit Libraria doesn't give you the copy of book but the location of the book. So if you tear page of the book and keep it same place. The librarian can aslo see torn page. But if you dont want this to happen. You need to get copy of the book and tear pages from it while the book on shelf will remain as it is.

So when you want to make the copy of the data and store it in a variable ES6 has introduced easy way to do it than earlier clumsy way. so this const filter = state.filter;

will become this const filter = [...state.filter]; // this makes copy of array

Kai
  • 331
  • 1
  • 3
  • 13
  • filter is just a boolean. no issue there. problem is with employees array. the spread operator will not solve issue since it's only doing shallow copy of nested array. The issue is why its changing global redux state?? – Kuldeep Bora Mar 04 '20 at 11:06
  • Its the same logic for all the const view = state.view; const filter = state.filter; const employees = state.employees; I just gave example considering filter. – Kai Mar 05 '20 at 06:53
1

I found the issue. useSelector will return a shallow copy of the nested objects, hence the mutation. The solution is to deep copy manually.

Kuldeep Bora
  • 4,072
  • 3
  • 12
  • 16