How to change state of an object attribute with React Hooks

Asked

Viewed 69 times

1

I have the following status with React Hooks:

const [active, setActive] = useState({
    card1: false,
    card2: false,
    card3: false,
    card4: false,
    card5: false,
    card6: false,
    card7: false,
});

I would like to do a function that receives an id that would be a card -for example:

function Mudar(id) {
     setActive((prevState) => {
       return { ...prevState, id: true };
     });
}

//depois chamo a função passando Mudar("card1") por exemplo

but instead of changing the card1 for true, for example, it creates a new id attribute and puts it to true.

You know why it happens and how I can fix it?

1 answer

2


You are creating a new item in this object because it was written in the code a name totally different from the others and so it copies the existing keys and creates an id with the value already mentioned.

What you need is as basic as possible with this change:

function Mudar(key) {
     setActive((prevState) => {
       return { ...prevState, [key]: true };
     });
}

At the time of the creation of card, need to recover the name of this key and pass the function as it was not mentioned the function or routine that creates these card may be incomplete in this regard.

An example code without knowing your:

function Card({name, status, click}) {
  return (
    <div>
      {name} - {status ? 'true': 'false'}
      {!status && (<button onClick={click}>Alterar</button>)}
    </div>
  )
}
function App() {
  const [active, setActive] = React.useState({
    card1: false,
    card2: false,
    card3: false,
    card4: false,
    card5: false,
    card6: false,
    card7: false,
  });
  function changeCard(key) {
     setActive((prevState) => {        
       return {...prevState, [key]: true};
     });
  }
  return (
    <div>
    {Object.entries(active).map((d,i) => 
        <Card 
            name={d[0]} key={i} 
            status={d[1]} 
            click={e => changeCard(d[0])}
        />)
    }
    </div>
  )
}

ReactDOM.render( <App/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root">Carregando ...</div>

This way as it is proposed in your question is not ideal, because, an object with several keys that are different by name should be a array of objects, an example modified with the reality of most developments to :

function Card({name, status, click}) {
  return (
    <div>
      {name} - {status ? 'true': 'false'}
      {!status && (<button onClick={click}>Alterar</button>)}
    </div>
  )
}
function App() {
  const [active, setActive] = React.useState([
    {name: 'card1', status: false},
    {name: 'card2', status: false},
    {name: 'card3', status: false},
    {name: 'card4', status: false},
    {name: 'card5', status: false},
    {name: 'card6', status: false},
    {name: 'card7', status: false},
  ]);
  function changeCard(obj) {
     setActive((prevState) => {          
       return [...prevState.map(a => {
        if (a.name === obj.name) {
          return {...a, status: true};
        }
        return a;
       })];
     });
  }
  return (
    <div>
    {active.map((d,i) => 
        <Card 
            name={d.name} key={i} 
            status={d.status} 
            click={e => changeCard(d)}
        />)
    }
    </div>
  )
}

ReactDOM.render( <App/> , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
<div id="root">Carregando ...</div>

thus the object with the property name is the unique key to this object in the array for changes, remove etc, could even be a numerical identification, but, it is enough for the demonstration where the list of values the operations are simpler.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.