Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we still need functional setState way in react hooks?

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

  const handleClick = () =>
    setCount(prevCount => {
      return prevCount + 1;
    });
  const [count, setCount] = useState(0);

  const handleClick = () => setCount(count + 1);

Coming from class-based component background, it becoming a habit where we use functional setState. I'm wondering if do we still need to rely on prevState in functional hooks? Or the current state is always "trustable" and most "updated"?

like image 890
Isaac Avatar asked Apr 04 '19 07:04

Isaac


People also ask

Which method replace setState in React hooks?

setState with the useState & useEffect hooks in React. This is a brief explanation of two of the most widely used hooks in React — useState & useEffect. There is also an example of how to replace a class component with a functional component and still declare and update state through the use of hooks.

Do you have to use setState in React?

Always use the setState() method to change the state object, since it will ensure that the component knows it's been updated and calls the render() method.

Can we use React hooks in functional component?

Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don't work inside classes — they let you use React without classes. (We don't recommend rewriting your existing components overnight but you can start using Hooks in the new ones if you'd like.)

Should I always use setState?

Safe to use setState ? Yes! This method is called whenever there is an update in the props or state. This method has arguments called nextProps and nextState can be compared with current props and currentState .


2 Answers

Yes, the behavior is similar.

React is batching the updates calls. When Writing:

const handleClick = () => setCount(count + 1)
handleClick()
handleClick()
handleClick()

the count in state will be 1

When Writing:

const handleClick = () =>
  setCount(prevCount => {
    return prevCount + 1;
});
handleClick()
handleClick()
handleClick()

the count in state will be 3

like image 112
Edan Chetrit Avatar answered Oct 18 '22 20:10

Edan Chetrit


State updater function is necessary in both class and functional components. this.setState shouldn't be used together with this.state, the same applies to useState state and state setter. There are more cases for useState when not using state updater will result in wrong behaviour.

In class components, the only problem with the use of this.state is race condition due to asynchronous state updates:

componentDidMount() {
  this.setState({ count: this.state.count + 1 });
  this.setState({ count: this.state.count + 1 }); // overwrites with stale count
  console.log(this.state.count); // not updated
}

When there are no race conditions, this.state can be accessed anywhere inside a component because this reference stays the same:

componentDidMount() {
  this.setState({ count: this.state.count + 1 });

  setTimeout(() => {
    this.setState({ count: this.state.count + 1 });
  }, 100)

  setTimeout(() => {
    console.log(this.state.count);
  }, 200)
}

In functional components, the problem with the use of useState state is function scope. There's no object like this that could be accessed by reference, a state is accessed by value which won't be updated until a component is re-rendered:

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

useEffect(() => {
  // runs once on mount
  // count is always 0 in this function scope

  setCount({ count: count + 1 });

  setTimeout(() => {
    setCount({ count: count + 1 }); // overwrites with stale count
  }, 100)

  setTimeout(() => {
    console.log(count); // not updated
  }, 200)
}, []);
like image 26
Estus Flask Avatar answered Oct 18 '22 20:10

Estus Flask