react-enhancer

1.0.5 • Public • Published

react-enhancer

Using state(defaultValue), refer https://reactjs.org/docs/hooks-reference.html#usestate

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const App = stateful((props, { state }) => {
  const defaultValue1 = 1;
  const defaultValue2 = 2;
  const [value1, setValue1] = state(defaultValue1);
  const [value2, setValue2] = state(defaultValue2);
 
  function handleCounter1() {
    setValue1(value1 + 1);
  }
 
  function handleCounter2() {
    setValue2(value2 + 1);
  }
 
  return (
    <>
      <button onClick={handleCounter1}>Increase Counter 1</button>
      <h2>Counter Value 1: {value1}</h2>
      <button onClick={handleCounter2}>Increase Counter 2</button>
      <h2>Counter Value 2: {value2}</h2>
    </>
  );
});
 
render(<App />, document.getElementById("root"));

Using ref(), refer https://reactjs.org/docs/hooks-reference.html#useref

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const App = stateful((props, { ref }) => {
  const inputRef = ref();
 
  function handleSubmit(e) {
    e.preventDefault();
    alert(inputRef.current.value);
  }
 
  return (
    <>
      <form onSubmit={handleSubmit}>
        <input ref={inputRef} />
      </form>
    </>
  );
});
 
render(<App />, document.getElementById("root"));

Using effect(factory, inputs), refer https://reactjs.org/docs/hooks-reference.html#useeffect

The default behavior for effects is to fire the effect once after completed render. That way an effect is always recreated if one of its inputs changes.

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const App = stateful((props, { effect, state }) => {
  const [userInfo, setUserInfo] = state("Loading...");
 
  effect(() => {
    setTimeout(
      () =>
        fetch("https://api.github.com/users/linq2js")
          .then(res => res.text())
          .then(res => setUserInfo(res)),
      2000
    );
  });
 
  return <>{userInfo}</>;
});
 
render(<App />, document.getElementById("root"));

Using use() to invoke custom hook

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const userInfoHook = ({ effect, state }, name) => {
  const [userInfo, setUserInfo] = state("Loading...");
  effect(() => {
    setTimeout(
      () =>
        fetch("https://api.github.com/users/" + name)
          .then(res => res.text())
          .then(res => setUserInfo(res)),
      2000
    );
  });
 
  return userInfo;
};
 
const App = stateful((props, { use }) => {
  const userInfo = use(userInfoHook, "linq2js");
 
  return <>{userInfo}</>;
});
 
render(<App />, document.getElementById("root"));

Using memo(factory, inputs), refer https://reactjs.org/docs/hooks-reference.html#usememo

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const App = stateful((props, { memo, state }) => {
  const [regenerated, setRegenerated] = state(false);
  const randomValue = memo(() => Math.random(), [regenerated]);
  const [counter, setCounter] = state(1);
 
  function handleRegenerated() {
    setRegenerated(!regenerated);
  }
 
  function handleCounter() {
    setCounter(counter + 1);
  }
 
  return (
    <>
      <button onClick={handleCounter}>Increase Counter</button>
      <h2>Counter Value: {counter}</h2>
      <button onClick={handleRegenerated}>Regenerate random value</button>
      <h2>Random Value: {randomValue}</h2>
    </>
  );
});
 
render(<App />, document.getElementById("root"));

Using context() to create simple todo app

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const initialState = [{ id: 1, text: "item 1" }, { id: 2, text: "item 2" }];
 
const reducer = (state, action) => {
  if (action.type === "add") {
    return [...state, { id: new Date().getTime(), text: action.payload }];
  }
  if (action.type === "remove") {
    return state.filter(todo => todo.id !== action.payload);
  }
  if (action.type === "toggle") {
    return state.map(todo =>
      todo.id === action.payload ? { ...todo, done: !todo.done } : todo
    );
  }
  return state;
};
 
const TodoForm = stateful((props, { ref, context }) => {
  const inputRef = ref();
 
  return context(({ dispatch }) => {
    function handleSubmit(e) {
      e.preventDefault();
      dispatch("add", inputRef.current.value);
      inputRef.current.value = "";
    }
 
    return (
      <form onSubmit={handleSubmit}>
        <input ref={inputRef} />
      </form>
    );
  });
});
 
const TodoList = stateful((props, { context }) => {
  return context(({ todos, dispatch }) => {
    return (
      <ul>
        {todos.map(todo => (
          <li key={todo.id} style={{ opacity: todo.done ? 0.5 : 1 }}>
            <button onClick={() => dispatch("toggle", todo.id)}>toggle</button>
            <button onClick={() => dispatch("remove", todo.id)}>remove</button>
            {todo.text}
          </li>
        ))}
      </ul>
    );
  });
});
 
const App = stateful((props, { context, state }) => {
  const [todos, setTodos] = state(initialState);
  const dispatch = (type, payload) =>
    setTodos(reducer(todos, { type, payload }));
  return context(
    { todos, dispatch },
    <>
      <TodoForm />
      <TodoList />
    </>
  );
});
 
render(<App />, document.getElementById("root"));

Using reducer(reducer, initialState) to create todo app

import React from "react";
import { render } from "react-dom";
import { stateful } from "react-enhancer";
 
const initialState = [{ id: 1, text: "item 1" }, { id: 2, text: "item 2" }];
 
const appReducer = (state, type, payload) => {
  if (type === "add") {
    return [...state, { id: new Date().getTime(), text: payload }];
  }
  if (type === "remove") {
    return state.filter(todo => todo.id !== payload);
  }
  if (type === "toggle") {
    return state.map(todo =>
      todo.id === payload ? { ...todo, done: !todo.done } : todo
    );
  }
  return state;
};
 
const TodoForm = stateful((props, { ref, context }) => {
  const inputRef = ref();
 
  return context(({ dispatch }) => {
    function handleSubmit(e) {
      e.preventDefault();
      dispatch("add", inputRef.current.value);
      inputRef.current.value = "";
    }
 
    return (
      <form onSubmit={handleSubmit}>
        <input ref={inputRef} />
      </form>
    );
  });
});
 
const TodoList = stateful((props, { context }) => {
  return context(({ todos, dispatch }) => {
    return (
      <ul>
        {todos.map(todo => (
          <li key={todo.id} style={{ opacity: todo.done ? 0.5 : 1 }}>
            <button onClick={() => dispatch("toggle", todo.id)}>toggle</button>
            <button onClick={() => dispatch("remove", todo.id)}>remove</button>
            {todo.text}
          </li>
        ))}
      </ul>
    );
  });
});
 
const handleTodosChange = console.log;
 
const App = stateful((props, { context, state, reducer }) => {
  const [todos, dispatch] = reducer(
    appReducer,
    initialState,
    handleTodosChange
  );
 
  return context(
    { todos, dispatch },
    <>
      <TodoForm />
      <TodoList />
    </>
  );
});
 
render(<App />, document.getElementById("root"));

Using store({ initialState, middleware, reducer, onChange }) to create redux like store

const TodoList = stateful((props, { context }) =>
  // extract todos from store
  context(({ todos, dispatch }) => (
    <ul>
      {todos.map(todo => (
        <li key={todo.id} style={{ opacity: todo.done ? 0.5 : 1 }}>
          <button
            onClick={() => dispatch({ type: "toggle", payload: todo.id })}
          >
            toggle
          </button>
          <button
            onClick={() => dispatch({ type: "remove", payload: todo.id })}
          >
            remove
          </button>
          {todo.text}
        </li>
      ))}
    </ul>
  ))
);
 
const handleStateChanged = state => console.log("state changed", state);
const loggerMiddleware = createLogger();
 
const App = stateful((props, { context, state, store }) => {
  return context(
    // create store and passing down to descendant components
    store({
      initialState,
      reducer: appReducer,
      middleware: loggerMiddleware,
      onChange: handleStateChanged
    }),
    <>
      <TodoForm />
      <TodoList />
    </>
  );
});

Package Sidebar

Install

npm i react-enhancer

Weekly Downloads

0

Version

1.0.5

License

MIT

Unpacked Size

238 kB

Total Files

7

Last publish

Collaborators

  • linq2js