Repository: react
Issue: Add `get` function to `useState`
Labels: Type: Discussion

<!--
  Note: if the issue is about documentation or the website, please file it at:
  https://github.com/reactjs/reactjs.org/issues/new
-->

**Do you want to request a *feature* or report a *bug*?**
- feature

**What is the current behavior?**
Code from [Introducing Hooks](https://reactjs.org/docs/hooks-intro.html):
```javascript
import { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
```
```javascript
// each time "count" changed, this arrow function will be created again.
// so that it can access the latest "count"
onClick={() => setCount(count + 1)}
```
I don't think it is good to create a fixed function many times, so I try to modify the code:
(Update on Jul 2022: No matter using the inline anonymous function or wrapping with `useCallback`, the function will always be created. The difference is that, in `useCallback` approach, the function reference will not be changed, which could be helpful if we use `memo` to wrap the component who receives the function as a property)
```javascript
const [count, setCount] = useState(0);
const handleClick = useCallback(() => setCount(count + 1), []);
```
But obviously the callback in `useCallback` couldn't get the latest `count` because I pass in an empty inputs array to avoid this callback been generated again and again.

So, in fact, the inputs array decide two things:
1. when to recreate the callback
2. which state can be accessed in the callback

In most situation, the two things are one thing, but here they conflict. 

So I think maybe it's good to add a `get` function to `useState` like this:
```javascript
import { useState, useCallback } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount, getCount] = useState(0);

  const handleClick = useCallback(() => setCount(getCount() + 1), []);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>
        Click me
      </button>
    </div>
  );
}
```
Maybe it's confusing because `getCount` can totally replace `count`, but it brings the possible to avoid creating callbacks again and again.

### Edited
https://github.com/facebook/react/issues/14543#issuecomment-452237355 exactly resolves the case above. But there‘re many other scenarios can't use `updater` to resolve. Here are some more code snippets:
#### 1. Access states in a timer.
```javascript
useEffect(() => {
  // or setInterval
  const id = setTimeout(() => {
    // access states
  }, period);
  return () => clearTimeout(id);
}, inputs);
```
#### 2. Access states in WebSocket callbacks
```javascript
useEffect(() => {
  // create a WebSocket client named "ws"
  ws.onopen = () => {
    // access states
  };
  ws.onmessage = () => {
    // access states
  };
  return () => ws.close();
}, inputs);
```
#### 3. Access states in Promise
```javascript
useEffect(() => {
  create_a_promise().then(() => {
    // access states
  });
}, inputs);
```
#### 4. Access states in event callbacks
```javascript
useEffect(() => {
  function handleThatEvent() {
    // access states
  }
  instance.addEventListener('eventName', handleThatEvent);
  return instance.removeEventListener('eventName', handleThatEvent);
}, inputs);
```

We had to use some workaround patterns to resolve those cases, like
https://github.com/facebook/react/issues/14543#issuecomment-452676760
https://github.com/facebook/react/issues/14543#issuecomment-453058025
https://github.com/facebook/react/issues/14543#issuecomment-453079958
Or a funny way:
```javascript
const [state, setState] = useState();
useEffect(() => {
  // or setInterval
  const id = setTimeout(() => {
    // access states
    setState((prevState) => {
      // Now I can do anything with state...🤮
      ...
      return prevState;
    });
  }, period);
  return () => clearTimeout(id);
}, inputs);
```

So let's discuss and wait...
https://github.com/facebook/react/issues/14543#issuecomment-452713416



**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:**

**What is the expected behavior?**

**Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?**
- React 16.7.0-alpha.2