1

React hook 使用规则

  1. 只在最顶层使用 Hook(不要在循环,条件或嵌套函数中调用 Hook)
  2. 只在 React 函数中调用 Hook(不要在普通的 JavaScript 函数中调用 Hook)

理解 hook 使用规则

规则2毋庸置疑,只在 react 组件中使用 state
规则2,对于初始使用者,可能会有些不习惯,那么我们下面来聊下为何时这样的,之后可能对这个就不再迷惑


function RenderFunctionComponent() {
  const [firstName, setFirstName] = useState("Rudi");
  const [lastName, setLastName] = useState("Yardley");

  return (
    <Button onClick={() => setFirstName("Fred")}>Fred</Button>
  );
}

我们来看下 hook 的一个大致流程是什么样的(并非react源码)

1.初始化


2.第一次渲染


3.后续渲染

4.事件处理

一个简单实现

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

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

// This is the pseudocode for the useState helper
export function useState(initVal) {
  if (firstRun) {
    state.push(initVal);
    setters.push(createSetter(cursor));
    firstRun = false;
  }

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

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

// Our component code that uses hooks
function RenderFunctionComponent() {
  const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
  const [lastName, setLastName] = useState("Yardley"); // cursor: 1

  return (
    <div>
      <Button onClick={() => setFirstName("Richard")}>Richard</Button>
      <Button onClick={() => setFirstName("Fred")}>Fred</Button>
    </div>
  );
}

// This is sort of simulating Reacts rendering cycle
function MyComponent() {
  cursor = 0; // resetting the cursor
  return <RenderFunctionComponent />; // render
}

console.log(state); // Pre-render: []
MyComponent();
console.log(state); // First-render: ['Rudi', 'Yardley']
MyComponent();
console.log(state); // Subsequent-render: ['Rudi', 'Yardley']

// click the 'Fred' button

console.log(state); // After-click: ['Fred', 'Yardley']

如果 hook 在条件中调用

let firstRender = true;

function RenderFunctionComponent() {
  let initName;
  
  if(firstRender){
    [initName] = useState("Rudi");
    firstRender = false;
  }
  const [firstName, setFirstName] = useState(initName);
  const [lastName, setLastName] = useState("Yardley");

  return (
    <Button onClick={() => setFirstName("Fred")}>Fred</Button>
  );
}

1.第一次渲染

2.第二次渲染

可以看到 lastName 读取了错误的值,所以可以看到顺序对 hook 来说为什么这么重要

使用 hook 开发

可以通过使用react-hooks 插件强制执行这些规则,实时提示。

本文参考了如下文章
https://medium.com/@ryardley/...

NsNe
1.7k 声望38 粉丝

善良,学习,拼搏。不忘初心,方得始终。