Last updated on

React Hooks 和 Effect handle function

Hooks 的顺序

下面的代码模拟了 hooks 的基本机制,可以参考回答一些 hooks 的问题

import { useEffect } from "react";
import ReactDOM from "react-dom/client";

const state = [];
const setters = [];
let firstRun = true;
let cursor = 0;

function createSetter(cursor) {
  return function setterWithCursor(newVal) {
    state[cursor] = newVal;
    render();
  };
}

export function useState(initVal) {
  if (firstRun) {
    state.push(initVal);
    setters.push(createSetter(cursor));
  }

  const setter = setters[cursor];
  const value = state[cursor];

  cursor++;
  return [value, setter];
}

function MyComponent() {
  const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
  const [lastName, setLastName] = useState("Yardley"); // cursor: 1

  return (
    <div>
      <button onClick={() => setFirstName(`${firstName}-Richard`)}>
        {firstName}
      </button>
      <button onClick={() => setLastName(`${lastName}-Fred`)}>
        {lastName}
      </button>
    </div>
  );
}

export function CustomUseStateDemo() {
  cursor = 0;
  console.log("state before render", JSON.parse(JSON.stringify(state)));
  const result = MyComponent();
  firstRun = false;
  console.log("state after render", JSON.parse(JSON.stringify(state)));
  return result;
}

let lastRoot;
const render = (root?) => {
  if (!root) {
    root = lastRoot;
  }
  lastRoot = root;
  root.render(<CustomUseStateDemo />);
};

export function Demo() {
  useEffect(() => {
    const root = ReactDOM.createRoot(document.getElementById("state"));
    render(root);
  }, []);
  return <div id="state"></div>;
}

image

演示可见 链接

image

useLayoutEffect 和 useEffect

image