In a class, we need to call this.setState() to update the count state:

<button onClick={() => this.setState({ count: this.state.count + 1 })}>    Click me
  </button>
In a function, we already have setCount and count as variables so we don’t need this:

<button onClick={() => setCount(count + 1)}>    Click me
  </button>
In the above component, we have age, fruit, and todos as local variables, and we can update them individually:

function handleOrangeClick() {
    // Similar to this.setState({ fruit: 'orange' })
    setFruit('orange');
  }
This is why in React classes, we put side effects into componentDidMount and componentDidUpdate. Coming back to our example, here is a React counter class component that updates the document title right after React makes changes to the DOM:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {    document.title = `You clicked ${this.state.count} times`;  }  componentDidUpdate() {    document.title = `You clicked ${this.state.count} times`;  }
  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

I believe it is a good approach, but you should use an functional state update. The "setter" functions of React.useState hook has a callback with previous state, so you shall update it like this:


import React from "react";

function MyComponent({id}) {
  const [list, setList] = React.useState([]);

  React.useEffect(() => {
    if (id) {
      setList(previousState => {
         return [
             ...previousState,
             id
         ];
      });
    }
  }, [id]);

  return (
    <div>
        {
            list.map((_id, index) => {
                <p key={index}>
                    {_id.toString()}
                </p>
            )
         }
    </div>
  );
}

This is because state is only initialized once. That's why the second value returned from useState() is a setter function. It's intended to be the only way to update the state after initialization. In this case you would use a useEffect() hook to update the state when props change (although there's not generally a great reason to initialize state with a prop).


const MyComponent = (prop1) => {
  
  const [myState, setState] = useState(prop1)

  useEffect(() => {
    setState(prop1)
  }, [prop1])

  return <>
    {myState && <div>Some text...</div>}
    <div onClick={() => setState(true)}>Click me</div>
  </>
}

This can be achieved using the useEffect hook.

Alternatively, you can set data.authors as part of the dependency array, such that the firstAuthorId state will be updated every time data.authors has changed.


useEffect(() => {
  setFirstAuthorId(data.authors[0].id)
}, []);


useEffect(() => {
  setFirstAuthorId(data.authors[0].id)
}, [data.authors]);
As we learned earlier, we can use multiple State or Effect Hooks in a single component:

function Form() {
  // 1. Use the name state variable
  const [name, setName] = useState('Mary');

  // 2. Use an effect for persisting the form
  useEffect(function persistForm() {
    localStorage.setItem('formData', name);
  });

  // 3. Use the surname state variable
  const [surname, setSurname] = useState('Poppins');

  // 4. Use an effect for updating the title
  useEffect(function updateTitle() {
    document.title = name + ' ' + surname;
  });

  // ...
}
Specifying [count] as a list of dependencies would fix the bug, but would cause the interval to be reset on every change. Effectively, each setInterval would get one chance to execute before being cleared (similar to a setTimeout.) That may not be desirable. To fix this, we can use the functional update form of setState. It lets us specify how the state needs to change without referencing the current state:

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + 1); // ✅ This doesn't depend on `count` variable outside    }, 1000);
    return () => clearInterval(id);
  }, []); // ✅ Our effect doesn't use any variables in the component scope
  return <h1>{count}</h1>;
}
If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value. Here’s an example of a counter component that uses both forms of setState:

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

Recommend

React Using the State Hook Reading State

React Using the State Hook Declaring a State Variable

React Using the State Hook What’s a Hook?

React Using the State Hook Hooks and Function Components

React Using the State Hook Equivalent Class Example

React Using the State Hook

React Handling Events Passing Arguments to Event Handlers

React Handling Events

React Hello World

React Rules of Hooks Explanation

React Rules of Hooks ESLint Plugin

React Introducing Hooks

ReactDOMServer Reference renderToStaticNodeStream()

ReactDOMServer Reference renderToNodeStream()

ReactDOMServer Reference renderToStaticMarkup()

ReactDOMServer Reference renderToString()

ReactDOMServer

React Testing Recipes Multiple Renderers

React Testing Recipes Snapshot Testing

React Testing Recipes Timers

React Testing Recipes Events

React Testing Recipes Mocking Modules

React Testing Recipes Data Fetching

React Testing Recipes Rendering

React Testing Recipes act()

React Testing Recipes Setup/Teardown

React Rendering Elements Updating the Rendered Element

React Rendering Elements Rendering an Element into the DOM

React Rendering Elements

React Component State What is the difference between passing an object or a function in setState?

React Component State Why is setState giving me the wrong value?

React Refs and the DOM Callback Refs

React Refs and the DOM Accessing Refs Refs and Function Components

React Refs and the DOM Accessing Refs Adding a Ref to a Class Component

React Refs and the DOM Accessing Refs Adding a Ref to a DOM Element

React Refs and the DOM Accessing Refs

React Refs and the DOM Creating Refs

File Structure Is there a recommended way to structure React projects? Grouping by file type

File Structure Is there a recommended way to structure React projects? Grouping by features or routes

Glossary of React Terms Components props.children

Glossary of React Terms Components props

Glossary of React Terms Components

Glossary of React Terms Elements

Glossary of React Terms JSX

React Code-Splitting Named Exports

React Code-Splitting Route-based code splitting

Code-Splitting React.lazy Error boundaries

Code-Splitting React.lazy

React Code-Splitting import()

React Code-Splitting Bundling Example

React Test Utilities Other Utilities Simulate

React Test Utilities Reference renderIntoDocument()

React Test Utilities Reference findRenderedComponentWithType()

React Test Utilities Reference scryRenderedComponentsWithType()

React Test Utilities Reference findRenderedDOMComponentWithTag()

React Test Utilities Reference scryRenderedDOMComponentsWithTag()

React Test Utilities Reference findRenderedDOMComponentWithClass()

React Test Utilities Reference scryRenderedDOMComponentsWithClass()

React Test Utilities Reference findAllInRenderedTree()

React Test Utilities Reference isCompositeComponentWithType()

React Test Utilities Reference isCompositeComponent()

React Test Utilities Reference isDOMComponent()

React Test Utilities Reference isElementOfType()

React Test Utilities Reference isElement()

React Test Utilities Reference mockComponent()

React Test Utilities Reference act()