1

I'm trying to remove specific item from my react state.

Current behavior:

When some of the checkboxes are selected, I'm updating their state. My useEffect have the checkboxes state for his dependency and every change I'm adding content only for the selected checkboxes.

Expected result:

When I'm unchecking some checkbox I want to remove the specific key from the "state" state.

Codesandbox for example: https://codesandbox.io/s/priceless-rgb-bon2f?file=/src/App.js

How can I remove it ? Thank you.

0

2 Answers 2

1

You can make a new object and set as that new object. Like this.

const newObject = Object.keys(state).reduce((object, item) => {
      if (item !== key) {
        object[item] = state[item];
      }
      return object;
    }, {});
Sign up to request clarification or add additional context in comments.

Comments

1

You can do it in handleChange.

  1. Remove unchecked i.e. false property name from the object. Or ...
  2. Add checked i.e. true property name in the object
const handleChange = (event) => {
  const { name, checked } = event.target;

  setState((prev) => {
    if (checked) {
      return { ...prev, [name]: `new value of ${name}` }; // Adding a new property
    }
    const { [name]: namesValue, ...rest } = prev; // Removing an old property
    return rest;
  });

};

Explanation:

To add a new property, create a new object using spread operator and add the new property and new value:

{ ...prev, [name]: `new value of ${name}` }

To remove an old property, discard one using computed object property name and rest in destructuring:

const { [name]: namesValue, ...rest } = prev;

Demo:

function App() {
  const [state, setState] = React.useState({
    a: "initial value of a",
    b: "initial value of b"
  })
  const [checked, setChecked] = React.useState({
    a: true,
    b: true,
  })

  const handleChange = (event) => {
    const { name, checked } = event.target

    setState((prev) => {
      if (checked) {
        return { ...prev, [name]: `new value of ${name}` }
      }
      const { [name]: namesValue, ...rest } = prev
      return rest
    })

    setChecked((prev) => ({ ...prev, [name]: checked }))
  }

  return (
    <div className="App">
      <label htmlFor="a">a</label>
      <input
        name="a"
        checked={checked.a}
        type="checkbox"
        id="a"
        onChange={handleChange}
      />

      <label htmlFor="b">b</label>
      <input
        name="b"
        checked={checked.b}
        type="checkbox"
        id="b"
        onChange={handleChange}
      />

      <div>{JSON.stringify(state)}</div>
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'))
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<body>
<div id="root"></div>
</body>

Edit:

If you want to have a separate useEffect hook to manage add/remove of property, you can use reduce as below:

useEffect(() => {
  setState((prev) => {
    return Object.keys(checked).reduce((obj, key) => {
      if (checked[key]) {
        obj[key] = prev[key] ?? `new value of ${key}`;
      }
      return obj;
    }, {});
  });
}, [checked]);

3 Comments

Great! Working now. Can I do the same thing with useEffect instead maybe? Thank you so much!
Thank you so much!!
See my edit above. Also, I have added a useEffect example in this codesandbox.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.