streamich / react-use

React Hooks — 👍
http://streamich.github.io/react-use
The Unlicense
41.92k stars 3.16k forks source link

Beyond React #471

Open streamich opened 5 years ago

streamich commented 5 years ago

Is any other library besides React using hooks? For example, does it make sense for use to make hooks library agnostic, instead of hardcoding it for React:

import { useState } from 'react';

const useUpdate = () => {
  const [, setState] = useState(0);
  return () => setState(cnt => cnt + 1);
};

Make it such that any library can inject their useState:

const useUpdate = ({ useState }) => () => {
  const [, setState] = useState(0);
  return () => setState(cnt => cnt + 1);
};
xobotyi commented 5 years ago

As I know—no.

wardoost commented 5 years ago

Preact 10 released this week with official support for hooks. I would expect react-use to work with Preact and its compatibility module but haven't actually tested it. However I did see an interesting note that concerns your question in the preact-compat readme:

There are better long-term ways to solve the coupling issue, like using factory functions that accept named generic methods (not just React DI), as suggested by Eric Elliot. However, since the React community has already authored so many modules in a more explicitly coupled manner, it's worth having a simple short-term solution for those who would like to liberate themselves from library lock-in.

As React seems to be library that is pushing things forward the quickest, for example Vue will implement hooks too, it makes sense to keep developing for React first and let compatibility layers like preact/compat solve this issue for now. Perhaps we could try to generalise react-use hooks at a later stage when other libraries have mature implementations of hook-like functionality.

streamich commented 5 years ago

If instead of waiting for compatibility layers we wanted to make Vue and Preact communities a nice surprise and make react-use hooks available for them, what would be the options? Below are some I was thinking about.

1. Use a factory function method
const useUpdate = ({ useState }) => () => {
  const [, setState] = useState(0);
  return () => setState(cnt => cnt + 1);
};
2. Import hooks from local module, that get's overwritten at build time
import { useState } from './hooks';

const useUpdate = () => {
  const [, setState] = useState(0);
  return () => setState(cnt => cnt + 1);
};

Then separate builds would be created for Vue and Preact, where the ./hooks module is overwritten appropriately.

3. Generic universal-hooks NPM module
import { useState } from 'universal-hooks';

const useUpdate = () => {
  const [, setState] = useState(0);
  return () => setState(cnt => cnt + 1);
};

There could be a universal-hooks NPM packages that would return the "right" set of hooks depending on environment. For example, if UNIVERSAL_HOOKS environment variable was set to "vue" it would return Vue hooks. This would allow to make most other React hook libraries universal, not just react-use.

Implementation could be something like this:

if (process.env.UNIVERSAL_HOOKS === 'vue') module.exports = require('vue-hooks');
else if (process.env.UNIVERSAL_HOOKS === 'preact') module.exports = require('preact-compat');
else module.exports = require('react');

One drawback of this approach would be that it would be hard to use multiple libraries, say React and Vue, at the same time in the same project.

4. Webpack alias

Use Webpack alias to overwrite, say react module with preact-compat, but this would work only for builds that use Webpack.

o-alexandrov commented 4 years ago

Great discussion, I'd vote for 2nd option, since users would be able to import separate packages vue-use, preact-use, etc.:

  1. Import hooks from local module, that get's overwritten at build time

On a side note, I haven't seen any issues when I migrated from react to preact, have you?