0

In React, there is function to update the state in the class component using setState. It has a callback function also which gets executed once the state is updated.

I want to do something similar with hooks. My requirement is: once the first state is updated then I want to update other states in a click handler in a functional component. How can we do this?

setFilterBy("read or unread");
setEmailList(list);

I have seen the following solution but this won't work for me as they are doing something in useEffect and here I want to do it in a click handler: How to use `setState` callback on react hooks

Krisztián Balla
  • 19,223
  • 13
  • 68
  • 84
N Sharma
  • 33,489
  • 95
  • 256
  • 444
  • 2
    *"I have seen this but this wont work for me as they are doing something in useEffect and here I want to do in click handler."* Can you give us a concrete example to work with? – T.J. Crowder Aug 23 '21 at 16:56
  • 1
    These two lines of code appear (by naming convention alone) to be setting state values for `filterBy` and `emailList`. In what way does this not work as expected? Do you have an example of a problem you're trying to solve? – David Aug 23 '21 at 17:00
  • You can take a look at this question https://stackoverflow.com/questions/56247433/how-to-use-setstate-callback-on-react-hooks – Lahcen Aug 23 '21 at 17:01
  • Here is the example https://codesandbox.io/s/loving-jennings-xphsd?file=/src/App.js – N Sharma Aug 23 '21 at 18:19
  • @NSharma - Please put your example **in** your question, not just linked. Three reasons: People shouldn't have to go off-site to help you; some sites are blocked for some users; and links rot, making the question and its answers useless to people in the future. You can make it a Stack Snippet (the `[<>]` toolbar button). Stack Snippets support React, including JSX; [here's how to do one](http://meta.stackoverflow.com/questions/338537/). – T.J. Crowder Aug 24 '21 at 05:18

2 Answers2

1

I have seen this but this wont work for me as they are doing something in useEffect and here I want to do in click handler.

Two answers for you there:

  1. You can just use the data that you call useState with in the click handler, you don't have to wait for the state to be set if you have other things you need to do. If those further things also involve setting state, this has the advantage that the state changes may get merged so your component doesn't re-render unnecessarily (which it may have been if you did further state changes in the setState callback). That's what you're doing in the code in the question:

    setFilterBy("read or unread");
    setEmailList(list);
    

    That's absolutely fine, nothing wrong with that. It won't cause two renders, state changes are merged where possible (and it will be possible with two setters one after another like that).

    More generally:

    // In the click handler:
    const theData = /*...figure out the data...*/;
    setTheData(theData);
    // ...do more things with `theData`...
    
  2. If you do want to wait for the state to be set before doing the things, you can do that in the component function itself (if it doesn't cause a state change) based on information stored in a ref, or in a useMemo callback (if it's just for performance reasons; there's no semantic guarantee), or (as you've found) in a useEffect or useLayoutEffect callback.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Here is the example https://codesandbox.io/s/loving-jennings-xphsd?file=/src/App.js can you see ? on L34 // here i want to call setFilterBy(null) then set other states. Problem is when you run the app tap on email then go in read emails it works then come back to unread emails then tap on mail is directly moving it in read list because filter is not null. – N Sharma Aug 23 '21 at 18:19
  • Any suggestions ?? – N Sharma Aug 24 '21 at 04:40
-1

to get what you want you need to use useEffect so basically you can have something like this:

const [emailList, setEmailList] = useState([]);

const whateverYouDoToCallTheStateUpdate = () => {
  setEmailList(['new user']);
}

useEffect(() => {
   console.log('the email changed, the new list is', emailList);
}, [emailList]);
Prince Hernandez
  • 3,623
  • 1
  • 10
  • 19