Repository: react
Issue: `useCallback()` & `useMemo()` automatically with a Babel Plug-in
Labels: Type: Discussion

**Do you want to request a *feature* or report a *bug*?**

Feature request.

**What is the current behavior?**

We need to `useCallback()` and `useMemo()` which seems redundant and can cost us in performance if not used right, which is likely to happen.

**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:**

```js
export default ({ data, sortComparator, filterPredicate, history }) => {
  const transformedData = data.filter(filterPredicate).sort(sortComparator)

  return (
    <div>
      <button className="back-btn" onClick={() => history.pop()} />
      <ul className="data-list">
        {transformedData.map(({ id, value }) => (
          <li className="data-item" key={id} onClick={() => history.push(`data/${id}`)}>{value}</li>
        ))}
      </ul>
    </div>
  )
}
```

**What is the expected behavior?**

Just like the [docs](https://reactjs.org/docs/hooks-reference.html#usecallback) suggest:

```
In the future, a sufficiently advanced compiler could create this array automatically.
```

Accordingly, I have implemented a Babel-plug-in that does exactly that; see [babel-plugin-react-persist](https://github.com/DAB0mB/babel-plugin-react-persist). Given the code snippet above, the plug-in should generate the following output:

```js
let _anonymousFnComponent, _anonymousFnComponent2

export default ({ data, sortComparator, filterPredicate, history }) => {
  const transformedData = React.useMemo(() =>
    data.filter(filterPredicate).sort(sortComparator)
  , [data, data.filter, filterPredicate, sortComparator])

  return React.createElement(_anonymousFnComponent2 = _anonymousFnComponent2 || (() => {
    const _onClick2 = React.useCallback(() => history.pop(), [history, history.pop])

    return (
      <div>
        <button className="back-btn" onClick={_onClick2} />
        <ul className="data-list">
          {transformedData.map(({ id, value }) =>
            React.createElement(_anonymousFnComponent = _anonymousFnComponent || (() => {
              const _onClick = React.useCallback(() =>
                history.push(`data/${id}`)
              , [history, history.push, id])

              return (
                <li className="data-item" key={id} onClick={_onClick}>
                  {value}
                </li>
              )
            }), { key: id })
          )}
        </ul>
      </div>
    )
  }), null)
}
```

The plug-in will:

- `useCallback()` automatically when a function is created.
- `useMemo()` automatically when a value is assigned.
- Will memoize inline callbacks.

I don't see however how can `useEffect()` be inferred automatically and if it's a good idea. The plug-in is not a feature request directly for React, but since it's stated in the docs I thought maybe it can be useful somehow. Maybe it can potentially be included as part of `create-react-app`? Would like to hear your thoughts about it. An alternative solution is suggested at #14406, but I don't see why do this at runtime when everything can be done ahead of time and save processing power.

**Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?**

React 16.8-alpha (hooks)