Skip to content

Instantly share code, notes, and snippets.

@bramblex
Created June 3, 2020 12:08
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 bramblex/7aa406fadfb114a8bf4a17e84ab1af80 to your computer and use it in GitHub Desktop.
Save bramblex/7aa406fadfb114a8bf4a17e84ab1af80 to your computer and use it in GitHub Desktop.
/* eslint-disable */
import React, { useMemo, useState } from "react";
function createHooksFromClass(_class) {
return function (props) {
const instance = useMemo(() => new _class(props), []);
const [state, setState] = useState(instance.state);
instance.state = state;
instance.props = props;
instance.setState = (newState) => setState(oldState => ({...oldState, ...newState}));
return instance.render();
};
}
export const Example = createHooksFromClass(
class {
state = {
count: 0,
};
constructor(props) {
this.state.count = props.count;
}
render() {
return (
<div>
<div>init: {this.props.count}</div>
<div>count: {this.state.count}</div>
<button onClick={() => this.setState({ count: this.state.count + 1})}>+</button>
<button onClick={() => this.setState({ count: this.state.count - 1})}>-</button>
</div>
);
}
}
);
import React from 'react'
const _stack = [];
export function useState(initial) {
const top = _stack[_stack.length - 1];
const n = top.count++;
if (!top.state.hasOwnProperty(n)) {
top.state[n] = initial;
}
return [top.state[n], (m) => top.setState({ [n]: m })];
};
export function withHooks(renderFunc) {
return class extends React.PureComponent {
count = 0;
state = {};
render() {
this.count = 0;
_stack.push(this);
console.log("push", _stack);
const result = renderFunc(this.props);
_stack.pop();
return result;
}
};
}
import React from "react";
import isEqual from "is-equal";
const _stack = [];
export function useState(initial) {
const top = _stack[_stack.length - 1];
const n = top.count++;
if (!top.state.hasOwnProperty(n)) {
top.state[n] = initial;
}
return [top.state[n], (m) => top.setState({ [n]: m })];
};
export function useEffect(effect, deps) {
const top = _stack[_stack.length - 1];
const n = top.count++;
if (!top.effect.hasOwnProperty(n)) {
top.effect[n] = { next: effect, deps, cleanup: null };
}
if (!isEqual(deps, top.effect[n].deps)) {
top.effect[n].next = effect;
top.effect[n].deps = deps;
}
}
export function withHooks(renderFunc) {
return class extends React.PureComponent {
count = 0;
state = {};
effect = {};
_context = {};
componentDidMount() {
this.componentDidUpdate();
}
componentDidUpdate() {
for (const effect of Object.values(this.effect)) {
if (effect.next) {
if (effect.cleanup) {
effect.cleanup();
}
effect.cleanup = effect.next();
effect.next = null;
}
}
}
componentWillUnmount() {
for (const { cleanup } of Object.values(this.effect)) {
if (cleanup) {
cleanup();
}
}
}
render() {
const result = this.renderFunc(this.props);
return result;
}
};
}
import React from "react";
import isEqual from "is-equal";
const _stack = [];
export function useState(initial) {
const top = _stack[_stack.length - 1];
const n = top.count++;
if (!top.state.hasOwnProperty(n)) {
top.state[n] = initial;
}
return [top.state[n], (m) => top.setState({ [n]: m })];
};
export function useEffect(effect, deps) {
const top = _stack[_stack.length - 1];
const n = top.count++;
if (!top.effect.hasOwnProperty(n)) {
top.effect[n] = { next: effect, deps, cleanup: null };
}
if (!isEqual(deps, top.effect[n].deps)) {
top.effect[n].next = effect;
top.effect[n].deps = deps;
}
}
export function useContext(context) {
const top = _stack[_stack.length - 1];
const n = top.count++;
if (!top._context.hasOwnProperty(n)) {
top._context[n] = {
value: context._currentValue,
context,
};
}
return top._context[n].value;
}
export function withHooks(renderFunc) {
return class extends React.PureComponent {
count = 0;
state = {};
effect = {};
_context = {};
constructor(props) {
super(props);
const renderFuncWithStack = () => {
_stack.push(this);
this.count = 0;
const result = renderFunc();
_stack.pop();
return result;
};
renderFuncWithStack();
this.renderFunc = Object.entries(this._context).reduceRight(
(lastRenderFunc, [n, { context }]) => () => (
<context.Consumer>
{(value) => {
this._context[n] = { value, context };
return lastRenderFunc();
}}
</context.Consumer>
),
renderFuncWithStack
);
}
componentDidMount() {
this.componentDidUpdate();
}
componentDidUpdate() {
for (const effect of Object.values(this.effect)) {
if (effect.next) {
if (effect.cleanup) {
effect.cleanup();
}
effect.cleanup = effect.next();
effect.next = null;
}
}
}
componentWillUnmount() {
for (const { cleanup } of Object.values(this.effect)) {
if (cleanup) {
cleanup();
}
}
}
render() {
const result = this.renderFunc(this.props);
return result;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment