Skip to content

Instantly share code, notes, and snippets.

@loganvolkers
Last active March 5, 2021 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loganvolkers/591dade9a38b2fcf26f9c19d001ca325 to your computer and use it in GitHub Desktop.
Save loganvolkers/591dade9a38b2fcf26f9c19d001ca325 to your computer and use it in GitHub Desktop.

Universal Hooks

A proposal for interoperability of React-style hooks.

Problem

  • React invented the hooks approach to functional components, but they are stuck in a framework-specific environment.
  • Haunted has created a pure JS alternative to React
  • Other frameworks (https://github.com/WebReflection/uland) also introduced hooks

If you're trying to write some composed state using the Hooks approach, you have to write to using one of these libraries implementation of useSate but the useState interface is actually generic and should be.

Proposal

An interface and a swappable implementation that can be used to implement universal custom hooks on top of hooks

Example

// universal-hooks.ts

const impl = {
  current: undefined
};
export function setImplementation(newImpl){
  impl.current = newImpl;
}

export function useState(newState){
  if(!impl.current) throw new Error("Universal hooks `setImplementation` should be called before hooks are used");
  return impl.current.useState(newState);
}

export function useEffect(cb,deps){
 /// ... etc,
}

Usage

import {useState} from "universal-hooks"

function useQuery(){
  const [data,setData] = useState(undefined);
}

Provide an implementation at runtime

An implementation can be provided at runtime. This is the most simple way to get started.

// index.js
import React from "React"
import {setImplementation} from "universal-hooks"
setImplementation(React);

Provide an implementation via bundlers

Rollup, Webpack and other bundlers allow compile-time replacement of implementations.

E.g. with the Rollup alias plugin https://github.com/rollup/plugins/tree/master/packages/alias

To swap in React

entries: [
  { find: 'universal-hooks', replacement: 'React' },
];

To swap in Haunted

entries: [
  { find: 'universal-hooks', replacement: 'haunted' },
];

Related issues:

  • Discussion between litelement creator Justin Fagnani and haunted created Matthew P about sharing hooks matthewp/haunted#130
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment