React hooks都是数组,没那么神秘

2021-03-09 20:29

阅读:591

标签:51cto   text   函数返回   需要   事件处理   const   技术   关联   function   

React hooks都是数组,没那么神秘

技术图片

图片
作者|Rudi Yardley
译者|无明
我是 hooks API 的忠实粉丝,不过它在使用方面确实存在一些奇怪的限制。在这篇文章里,我提出了一个模型,为那些难以理解 hooks API 使用规则的人提供一种思路。

解开 hooks 的原理

我看到有些人把新的 hooks API 提案看成是一种神奇的“魔术”,所以我试着至少从表层来解释一下新的语法提案。
hooks 的规则
React 核心团队规定了两个主要的使用规则,并在 hooks 提案文档中给出了概述。

  • 不要在循环、条件或嵌套函数中调用 hook;
  • 只从 React Function 从调用 hook。
    我认为后者是不言自明的。要将行为附加到函数式组件,你需要能够以某种方式将行为与组件相关联。
    我认为可能会令人感到困惑的是前者,因为使用这样的 API 进行编程似乎有点不自然,而这就是我今天要探讨的内容。
    hooks 中的状态管理都是关于数组
    为让你在头脑里有个清晰的印象,先让我们看看一个简单的 hooks API 实现可能是什么样子。
    如何实现useState()?
    首先让我们从一个组件开始:

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

    hooks API 的原理是将一个 setter 函数作为 hook 函数返回的第二个数组项,这个 setter 将控制由 hook 管理的状态。

    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;

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 (





);
}

// This is sort of simulating Reacts rendering cycle
function MyComponent() {
cursor = 0; // resetting the cursor
return ; // 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 顺序会怎样?
让我们来做一些 React 团队不建议我们做的事情:

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 (

);
}


我们在条件中调用了 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都是数组,没那么神秘

标签:51cto   text   函数返回   需要   事件处理   const   技术   关联   function   

原文地址:https://blog.51cto.com/15057848/2568237


评论


亲,登录后才可以留言!