React hooks都是数组,没那么神秘
2021-03-09 20:29
标签:51cto text 函数返回 需要 事件处理 const 技术 关联 function 图片 我看到有些人把新的 hooks API 提案看成是一种神奇的“魔术”,所以我试着至少从表层来解释一下新的语法提案。 只从 React Function 从调用 hook。 hooks API 的原理是将一个 setter 函数作为 hook 函数返回的第二个数组项,这个 setter 将控制由 hook 管理的状态。 以下示例将在执行上下文中渲染特定组件。也就是说,这里保存的数据位于被渲染组件之外。这个状态不与其他组件共享,但它所在的作用域可以被随后渲染的特定组件访问。 简单的实现 function createSetter(cursor) { // This is the pseudocode for the useState helper const setter = setters[cursor]; cursor++; // Our component code that uses hooks return ( // This is sort of simulating Reacts rendering cycle console.log(state); // Pre-render: [] // click the ‘Fred‘ button console.log(state); // After-click: [‘Fred‘, ‘Yardley‘] let firstRender = true; function RenderFunctionComponent() { if(firstRender){ return ( React hooks都是数组,没那么神秘 标签:51cto text 函数返回 需要 事件处理 const 技术 关联 function 原文地址:https://blog.51cto.com/15057848/2568237
作者|Rudi Yardley
译者|无明
我是 hooks API 的忠实粉丝,不过它在使用方面确实存在一些奇怪的限制。在这篇文章里,我提出了一个模型,为那些难以理解 hooks API 使用规则的人提供一种思路。解开 hooks 的原理
hooks 的规则
React 核心团队规定了两个主要的使用规则,并在 hooks 提案文档中给出了概述。
我认为后者是不言自明的。要将行为附加到函数式组件,你需要能够以某种方式将行为与组件相关联。
我认为可能会令人感到困惑的是前者,因为使用这样的 API 进行编程似乎有点不自然,而这就是我今天要探讨的内容。
hooks 中的状态管理都是关于数组
为让你在头脑里有个清晰的印象,先让我们看看一个简单的 hooks API 实现可能是什么样子。
如何实现useState()?
首先让我们从一个组件开始:function RenderFunctionComponent() {
const [firstName, setFirstName] = useState("Rudi");
const [lastName, setLastName] = useState("Yardley");
return (
);
}
React 要用它来做什么?
1)初始化
创建两个空数组:setters和state
将游标设置为 0
图片
2)首次渲染
首次运行组件函数。
在首次运行时,每次调用 useState() 都会将 setter 函数添加到 setter 数组中,然后将某种状态添加到 state 数组。
图片
3)后续的渲染
每次后续的渲染都会重置游标,并且游标的值都是从每个数组中读取的。
图片
4)事件处理
每个 setter 都有一个对游标位置的引用,因此,通过调用 setter 就会改变 state 数组中相应的值。
这是一个简单的代码实现示例:
let state = [];
let setters = [];
let firstRun = true;
let cursor = 0;
return function setterWithCursor(newVal) {
state[cursor] = newVal;
};
}
export function useState(initVal) {
if (firstRun) {
state.push(initVal);
setters.push(createSetter(cursor));
firstRun = false;
}
const value = state[cursor];
return [value, setter];
}
function RenderFunctionComponent() {
const [firstName, setFirstName] = useState("Rudi"); // cursor: 0
const [lastName, setLastName] = useState("Yardley"); // cursor: 1
);
}
function MyComponent() {
cursor = 0; // resetting the cursor
return
}
MyComponent();
console.log(state); // First-render: [‘Rudi‘, ‘Yardley‘]
MyComponent();
console.log(state); // Subsequent-render: [‘Rudi‘, ‘Yardley‘]# 为什么顺序很重要
如果我们根据某些外部因素或组件状态更改渲染周期的 hooks 顺序会怎样?
让我们来做一些 React 团队不建议我们做的事情:
let initName;
[initName] = useState("Rudi");
firstRender = false;
}
const [firstName, setFirstName] = useState(initName);
const [lastName, setLastName] = useState("Yardley");
);
}
我们在条件中调用了 useState。现在让我们看看它对系统造成的破坏。
坏组件的首次渲染
![](https://s4.51cto.com/images/blog/202012/20/ad149e673338ccf1fb68d05bb2c31191.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
实例变量 firstName 和 lastName 包含正确的数据,现在让我们来看看第二次渲染会发生什么:
坏组件的第二次渲染
![](https://s4.51cto.com/images/blog/202012/20/943491b469f4342c5b73b59c51578025.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
firstName 和 lastName 都设置为“Rudi”,因为 state 存储变得不一致。这显然是错误的,不过这很清楚地说明为什么 React 团队要为 hooks 制定这样的规则。
如果不遵从 React 团队制定的使用规则,就会导致数据不一致。
让 hooks 操作一组数组,这样就不会违反规则
现在应该很清楚为什么不能在条件或循环中调用use hooks。因为我们正在处理指向一组数组的游标,所以如果更改了渲染的调用顺序,游标就无法与数据匹配,你的调用就不会指向正确的数据或处理程序。
解决办法是让 hooks 管理一组数组,这组数组需要一个一致的游标。如果这么做了,就不会违反规则。
# 结论
hooks 是 React 组件的一个很有用的插件 API。人们对它感兴奋是有原因的,并且如果你将这种模型视为一组数组,那么在使用它们时就不会违反规则。
英文原文:
https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e
活动推荐
推荐大家关注由 InfoQ 中国主办的 ArchSummit 全球架构师峰会,大会即将于 12 月 7-8 日在北京国际会议中心举办,来自 Google、Netflix、LinkedIn、腾讯、阿里、百度、京东等百位知名企业的架构师都将前来分享各自的架构实践,并特别设置了前端技术专题,分享他们的最新黑科技和研发经验。
9 折优惠购票火热进行中,点击“阅读原文”了解更多详情!票务 MM 灰灰联系方式:17326843116 (微信同号 等你来撩)
文章标题:React hooks都是数组,没那么神秘
文章链接:http://soscw.com/index.php/essay/62438.html