美文网首页
React HooK简介

React HooK简介

作者: 菜菜的小阿允 | 来源:发表于2020-09-15 14:37 被阅读0次

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

一、为什么会在 React 中加入 Hook,以及如何使用 Hook 写出更好的应用。
  • 在组件之间复用状态逻辑很难
    React 没有提供将可复用性行为“附加”到组件的途径(例如,把组件连接到 store)。虽然可以使用render props高阶组件来解决,但是这类方案需要重新组织你的组件结构,这样可能会使你的代码难以理解。React 需要为共享状态逻辑提供更好的原生途径。
    你可以使用 Hook 从组件中提取状态逻辑,使得这些逻辑可以单独测试并复用。Hook 使你在无需修改组件结构的情况下复用状态逻辑。 这使得在组件间或社区内共享 Hook 变得更便捷。
  • 复杂组件变得难以理解
    例如,同一个 componentDidMount 中可能包含很多其它的逻辑(如设置事件监听和获取数据),而之后需在 componentWillUnmount 中清除。相互关联且需要对照修改的代码被进行了拆分,而完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。
    为了解决这个问题,Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分。你还可以使用 reducer 来管理组件的内部状态,使其更加可预测。
  • 难以理解的 class
    class 是学习 React 的一大屏障,你必须去理解 JavaScript 中 this 的工作方式,还不能忘记绑定事件处理器。class 也给目前的工具带来了一些问题。例如,class 不能很好的压缩,并且会使热重载出现不稳定的情况。因此,我们想提供一个使代码更易于优化的 API。
    为了解决这些问题,Hook 使你在非 class 的情况下可以使用更多的 React 特性。 从概念上讲,React 组件一直更像是函数。而 Hook 则拥抱了函数,同时也没有牺牲 React 的精神原则。Hook 提供了问题的解决方案,无需学习复杂的函数式或响应式编程技术。
二、Hook 概览
  • 使用State Hook
  1. 例子:
import React, { useState } from 'react';
function Example () {
    const [count, setCount] = useState(0);
    return (
        <div>
            <p>you click {count} times</p>
            <button onClick={ () => setCount(count + 1)}>click</button>
        </div>
    )
}

第一行: 引入 React 中的 useState Hook。它让我们在函数组件中存储内部 state。
第三行: 在 Example 组件内部,我们通过调用 useState Hook 声明了一个新的 state 变量。它返回一对值给到我们命名的变量上。我们把变量命名为 count,因为它存储的是点击次数。我们通过传 0 作为 useState 唯一的参数来将其初始化为 0。第二个返回的值本身就是一个函数。它让我们可以更新 count 的值,所以我们叫它 setCount。
第七行: 当用户点击按钮后,我们传递一个新的值给 setCount。React 会重新渲染 Example 组件,并把最新的 count 传给它。

  1. 使用多个 state 变量

将 state 变量声明为一对 [something, setSomething] 也很方便,因为如果我们想使用多个 state 变量,它允许我们给不同的 state 变量取不同的名称:

const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: '学习 Hook' }]);
  • 使用 Effect Hook
  1. 例子
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

我们声明了 count state 变量,并告诉 React 我们需要使用 effect。紧接着传递函数给 useEffect Hook。此函数就是我们的 effect。然后使用 document.title 浏览器 API 设置 document 的 title。我们可以在 effect 中获取到最新的 count 值,因为他在函数的作用域内。当 React 渲染组件时,会保存已使用的 effect,并在更新完 DOM 后执行它。这个过程在每次渲染时都会发生,包括首次渲染。每次重新渲染,都会生成新的 effect,替换掉之前的。某种意义上讲,effect 更像是渲染结果的一部分 —— 每个 effect “属于”一次特定的渲染。

  1. effect hook的小提示
    (1)通过跳过 Effect 进行性能优化
    在某些情况下,每次渲染后都执行清理或者执行 effect 可能会导致性能问题。在 class 组件中,我们可以通过在 componentDidUpdate 中添加对 prevProps 或 prevState 的比较逻辑解决:
componentDidUpdate(prevProps, prevState) {
if (prevState.count !== this.state.count) {
  document.title = `You clicked ${this.state.count} times`;
}
}

如果某些特定值在两次重渲染之间没有发生变化,你可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可:

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // 仅在 count 更改时更新

(2)使用多个 Effect 实现关注点分离
使用 Hook 其中一个目的就是要解决 class 中生命周期函数经常包含不相关的逻辑,但又把相关逻辑分离到了几个不同方法中的问题:

class FriendStatusWithCounter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0, isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }

  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }

可以发现设置 document.title 的逻辑是如何被分割到 componentDidMount 和 componentDidUpdate 中的,订阅逻辑又是如何被分割到 componentDidMount 和 componentWillUnmount 中的。而且 componentDidMount 中同时包含了两个不同功能的代码。

Hook 允许我们按照代码的用途分离他们,而不是像生命周期函数那样。React 将按照 effect 声明的顺序依次调用组件中的每一个effect。

function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
}
三、Hook 规则

Hook 本质就是 JavaScript 函数,但是在使用它时需要遵循两条规则。

  • 只在最顶层使用 Hook
    不要在循环,条件或嵌套函数中调用 Hook,确保总是在你的 React 函数的最顶层调用他们。遵守这条规则,你就能确保 Hook 在每一次渲染中都按照同样的顺序被调用。这让 React 能够在多次的 useStateuseEffect 调用之间保持 hook 状态的正确。

  • 只在 React 函数中调用 Hook
    不要在普通的 JavaScript 函数中调用 Hook。可以在 React 的函数组件中调用 Hook或在自定义 Hook 中调用其他 Hook

如果我们想要有条件地执行一个 effect,可以将判断放到 Hook 的内部:

useEffect(function persistForm() {
    // 将条件判断放置在 effect 中
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

相关文章

  • React HooK简介

    Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他...

  • React Hook简介

    本文引自 https://zh-hans.reactjs.org/docs/hooks-intro.html Ho...

  • React Hook - 简介

    可以在不编写 class 的情况下使用 state 以及其他 React 特性 为什么要引入 hooks? 在组件...

  • React Hook

    Hook 简介 State Hook React 假设当你多次调用 useState 的时候,你能保证每次渲染时它...

  • react hook

    hook 简介 Hook 是一个特殊的函数,它可以让你“钩入” React 的特性,常见的hook如下: useS...

  • hook的使用总结

    hook简介 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 sta...

  • React hook 10种 Hook

    React hook 10种 Hook (详细介绍及使用) React Hook是什么?React官网是这么介绍的...

  • react hook - 简介 & 概览

    简介 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以...

  • react hook 新特性汇总

    Hook 简介 Hook是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数, 是 ...

  • 学习react hook的总结

    react16推出了react hook,react hook使得functional组件拥有了class组件的一...

网友评论

      本文标题:React HooK简介

      本文链接:https://www.haomeiwen.com/subject/ynmxyktx.html