润滑油东莞网站建设,如何寻找做网站的客户,永州静默管理,做网站互联网公司排名[译] React Hooks: 没有魔法#xff0c;只是数组 原文链接#xff1a; medium.com/ryardley/r… 我是 React 新特性 Hooks 的粉丝。但是#xff0c;在你使用 React Hooks的过程中#xff0c;有一些看上去 很奇怪的限制 。在本文里#xff0c;对于那些还在为了理解这些限制… [译] React Hooks: 没有魔法只是数组 原文链接 medium.com/ryardley/r… 我是 React 新特性 Hooks 的粉丝。但是在你使用 React Hooks的过程中有一些看上去 很奇怪的限制 。在本文里对于那些还在为了理解这些限制而苦苦挣扎的同志我尝试通过一些列图表的方式来解释为什么会存在这些限制。 理解hooks怎么运行 我听说很多同学都对hooks像魔法一般的效果感到困惑因此我将尝试通过浅显的方式来演示hooks是怎么运行的。 hooks的原则 react团队在怎么使用hooks的 官方文档 中强调了两点主要的使用原则 不要 在 循环、条件语句或者嵌套函数中调用hooks 只能在 React 函数组件中调用hooks 第二点我认为是显而易见的。为了给 函数组件 增加一些能力(比如 state类声明周期方法)你当然需要通过一种方式来把这种能力赋给函数组件这种方式就是使用hooks。 然而第一点规则很容易让人感到困惑。不就是使用一个 API 么为什么还有这么多限制呢。这也正是我将要在下文里解释的。 hooks中的state管理只是在操作数组 为了更加清晰的理解hooks让我们来看看怎么简单实现hooks API。 请注意下面代码只是一个demo是为了让我们理解hooks大概是怎么运作的。这不是 React 中的真正内部实现。 怎么实现 useState 呢 让我们通过一个例子来演示useState内部大概是怎么运作的。 组件代码如下 function RenderFunctionComponent() {const [firstName, setFirstName] useState(Rudi);const [lastName, setLastName] useState(Yardley);
return (Button onClick{() setFirstName(Fred)}Fred/Button);
}
复制代码useState 实现的功能是你能通过这个hook返回的 数组 中第二个元素作为修改这个state的一个setter方法。 那么React可能会怎么来实现 useState 呢 让我们来想想react内部会怎么来实现 useState 呢。在下面的实现里state 是存放在被render的组件外面并且这个state不会和其他组件共享同时在这个组件后续render中能够通过特定的作用域方式访问到这个state。 1) state初始化 创建两个空数组分别用来存放 setters 和 state将 指针 指到 0 的位置 2) 组件首次render 当首次render这个函数组件的时候。 每一个 useState 调用当 首次 执行的时候在 setter 数组里加入一个 setter 函数(和对应的数组index关联)然后将 state 加入对应的 state 数组里 3) 组件后续(非首次)render 后续组件的每次render指针都会重置为 0 每调用一次 useState都会返回指针对应的两个数组里的 state 和 setter然后将指针位置 1。 4)setter调用处理 每一个 setter 函数都关联了对应的指针位置。当调用某个 setter 函数式就可以通过这个函数所关联的指针找到对应的 state修改state数组里对应位置的值 最后来看看useState简单的实现 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: 0const [lastName, setLastName] useState(Yardley); // cursor: 1
return (divButton onClick{() setFirstName(Richard)}Richard/ButtonButton onClick{() setFirstName(Fred)}Fred/Button/div);
}
// This is sort of simulating Reacts rendering cycle
function MyComponent() {cursor 0; // resetting the cursorreturn 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]
复制代码为什么hooks的调用顺序不能变呢 如果我们根据某些外部变量或者组件自身的state改变hooks的调用顺序会有什么后果呢 我们来演示下 错误的 做法 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);
}
复制代码上面代码里我们第一个 useState 是在一个 条件分支里。我们来看看这样引入的bug。 1) 第一次render 第一个render之后我们的两个statefirstName 和 lastName 都对应了正确的值。接下来看看组件第二次render的时候会发生什么情况。 2) 第二次render 第二次render之后我们的两个state firstName和 lastName 都成了 Rudi。这显然是错误的必须要避免这样使用hooks但是这也给我们演示了hooks的调用顺序为什么不能改变。 react团队明确强调了hooks的2个使用原则如果不按照这些原则来使用hooks将会导致我们数据的不一致性 将hooks的操作想象成数组的操作你可能不太会违背这些原则 OK现在你应该清楚为什么我们不能在条件块或者循环语句里调用hooks了。因为调用hooks的过程中我们是在操作数组上的指针如果你在多次render中改变了hooks的调用顺序将导致数组上的指针和组件里的 useState 不匹配从而返回错误的 state 以及 setter 。 结论 希望我基本讲明白了hooks调用顺序的大概原理。hooks是对react生态的一个很好的优化。人们对hooks感到兴奋是有原因的。如果你将hooks的操作当做数组一样来看待那么你一般不会违背hooks的使用原则。 转载于:https://juejin.im/post/5ce8071ff265da1bd30534c9