简体   繁体   中英

React hooks: How do I update state with object

I have 3 components like this, how I update state in App component

How I update state onclick in Counter component

import React, { useState } from 'react'
import Header from './components/Header'
import Counters from './components/Counters'

const App = () => {
  const initialCounters = [
    { id: 1, value: 0 },
    { id: 2, value: 0 },
    { id: 3, value: 0 },
    { id: 4, value: 0 },
  ]
  const [counters, setCounters] = useState(initialCounters)

  const onIncrement = (counter) => {
    console.log(counter)
  }

  return (
    <>
      <Header totalCounters={counters.length} />
      <main className='container'>
        <Counters counters={counters} onIncrement={onIncrement} />
      </main>
    </>
  )
}

export default App

In your Counters component when you call the OnIncrement method you need to pass it's id as reference.

Then in your OnIncrement you do this

  const onIncrement = (counterId) => {
    const updatededCounters = counters.map((counter) => {
     if(counter.id === counterId){
      counter.value++
      return counter     
      }
      return counter
     })
     setCounters(updatededCounters)
  }

Just to be clear in your Counters component

import React from "react";

const Counters = ({ counters, onIncrement }) => {
  return (
    <>
      {counters.map((counter) => (
        <div key={counter.id}>
          <p>My counter : {counter.value}</p>
          <button onClick={() => onIncrement(counter.id)}>Increment</button>
        </div>
      ))}
    </>
  );
};

Full code for the parent component

import React, { useState } from "react";
import Counters from "./Counters";

const App = () => {
  const initialCounters = [
    { id: 1, value: 0 },
    { id: 2, value: 0 },
    { id: 3, value: 0 },
    { id: 4, value: 0 }
  ];
  const [counters, setCounters] = useState(initialCounters);
  const onIncrement = (counterId) => {
    const updatededCounters = counters.map((counter) => {
      if (counter.id === counterId) {
        counter.value++;
        return counter;
      }
      return counter;
    });
    setCounters(updatededCounters);
  };

  return (
    <>
      <main className="container">
        <Counters counters={counters} onIncrement={onIncrement} />
      </main>
    </>
  );
};

export default App;

Codesandbox link: https://codesandbox.io/s/sad-chebyshev-l4hez?file=/src/App.js:0-725

Explanation

What i do the onIncrement method is simple: i will create a new array with values i want to edit inside of it, then i'll set the state with this new array.

In the.map() Each instance of counter will be looped, so for each instance i check if one of them is the one im looking for to update (with the same id as the counterId i receive as parameter)

If so, i edit the value of the current counter and then return the counter instance to allow the loop to continue to the next one.

When the counter id is not the same as the counterId received, i just return the counter without any modification.

So at the end, you will get the same array of values, exepct for the specific counter you incremented where you will see it's value updated by one count

I advice you to read some documentation about.map() function since it's really used in react: https://fr.reactjs.org/docs/lists-and-keys.html

And aswell you coud look into Object.keys() beceause it's often used with.map() aswell if you need to loop through object properties: https://reedbarger.com/how-to-transform-javascript-objects-the-power-of-objectkeys-values-entries/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM