10分钟相识react新特征hooks

Hook 简介

HookReact 16.8 的新增特征。它能够让你在不编写 class 的情况下运用 state 以及其他的 React 特征。

useState

这个例子用来显现一个计数器。当你点击按钮,计数器的值就会增添:

import React, { useState } from 'react';

function Example() {
  // 声明一个新的叫做 “count” 的 state 变量
  const [count, setCount] = useState(0);

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

useState 唯一的参数就是初始 state。在上面的例子中,我们的计数器是从零开始的,所以初始 state 就是 0。

声明多个 state 变量

你能够在一个组件中屡次运用 State Hook:

function ExampleWithManyStates() {
  // 声明多个 state 变量!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

Effect Hook

你之前能够已在 React 组件中实行过数据猎取、定阅或许手动修悛改 DOM。我们一致把这些操纵称为“副作用”,或许简称为“作用”。

useEffect 就是一个 Effect Hook,给函数组件增添了操纵副作用的才能。它跟 class 组件中的 componentDidMountcomponentDidUpdatecomponentWillUnmount 具有雷同的用处,只不过被兼并成了一个 API

能够关照 React 跳过对 effect 的挪用,只需通报数组作为 useEffect 的第二个可选参数即可:

比方,下面这个组件在 React 更新 DOM 后会设置一个页面题目:

import React, { useState, useEffect } from 'react';

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

  // 相当于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 运用浏览器的 API 更新页面题目
    document.title = `You clicked ${count} times`;
  }[count]); // 仅在 count 变动时更新

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

当你挪用 useEffect 时,就是在通知 React 在完成对 DOM 的变动后运转你的“副作用”函数。由于副作用函数是在组件内声明的,所以它们能够访问到组件的 propsstate。默许情况下,React 会在每次衬着后挪用副作用函数 —— 包括第一次衬着的时刻。

副作用函数还能够经由过程返回一个函数来指定怎样“消灭”副作用。比方,鄙人面的组件中运用副作用函数来定阅挚友的在线状况,并经由过程作废定阅来举行消灭操纵:

import React, { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);

    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

在这个示例中,React 会在组件烧毁或许后续衬着从新实行副作用函数时作废对 ChatAPI 的定阅。(假如传给 ChatAPIprops.friend.id 没有变化,你也能够通知 React 跳过从新定阅。)

Hook 运用划定规矩

Hook 就是 JavaScript 函数,然则运用它们会有两个分外的划定规矩:

  • 只能在函数最外层挪用 Hook。不要在轮回、前提推断或许子函数中挪用。
  • 只能在 React 的函数组件中挪用 Hook。不要在其他 JavaScript 函数中挪用。

自定义 Hook

有时刻我们会想要在组件之间重用一些状况逻辑。目前为止,有两种主流计划来处理这个题目:高阶组件和 render props。自定义 Hook 能够让你在不增添组件的情况下到达一样的目标。

前面,我们引见了一个叫 FriendStatus 的组件,它经由过程挪用 useStateuseEffectHook 来定阅一个挚友的在线状况。假定我们想在另一个组件里重用这个定阅逻辑。

起首,我们把这个逻辑抽取到一个叫做 useFriendStatus 的自定义 Hook 里:

import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

它将 friendID 作为参数,并返回该挚友是不是在线:

如今我们能够在两个组件中运用它:

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

这两个组件的 state 是完整自力的。Hook 是一种复用状况逻辑的体式格局,它不复用 state 自身。事实上 Hook 的每次挪用都有一个完整自力的 state —— 因而你能够在单个组件中屡次挪用同一个自定义 Hook

自定义 Hook 更像是一种商定而不是功用。假如函数的名字以 “use” 开首并挪用其他 Hook,我们就说这是一个自定义 Hook

其他Hooks

  • useReducer

useState 的替换计划。它吸收一个形如 (state, action) => newStatereducer,并返回当前的 state 以及与其配套的 dispatch 要领。(假如你熟习 Redux 的话,就已晓得它怎样工作了。)

在某些场景下,useReducer 会比 useState 更实用,比方 state 逻辑较庞杂且包括多个子值,或许下一个 state 依赖于之前的 state 等。而且,运用 useReducer 还能给那些会触发深更新的组件做机能优化,由于你能够向子组件通报 dispatch 而不是回调函数 。

以下是用 reducer 重写 useState 计数器示例:

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
  );
}
  • useContext
    原文作者:Weibozzz
    原文地址: https://segmentfault.com/a/1190000019324967
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞