react之 hook 相关知识点

  • useState
    const [state, setState] = useState(initialState);

    返回一个 state,以及更新 state 的函数。

    在初始渲染期间,返回的状态 (state) 与传入的第一个参数 (initialState) 值相同。

    setState 函数用于更新 state。它接收一个新的 state 值并将组件的一次重新渲染加入队列。

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>
  );
}

我们可以使用多个 state 变量,并给不同的 state 变量取不同的名称:

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

  //...
  
}

我们还可以单独更新其中一个

 function handleSetFruitClick() {
    // 和 this.setState({ fruit: 'orange' }) 类似
    setFruit('orange');
  }



  • useEffect
    useEffect Hook 可以看做React class 的生命周期函数里面的 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
    它在第一次渲染之后和每次更新之后都会执行

    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>
      );
    }
    

    有一些副作用的操作需要在组件卸载的时候去清除的时候,useEffect函数为我们提供了一个钩子函数:

    import React, { useState, useEffect } from 'react';
    
    function FriendStatus(props) {
      const [isOnline, setIsOnline] = useState(null);
    
      useEffect(() => {
        function handleStatusChange(status) {
          setIsOnline(status.isOnline);
        }
        ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
       
        //在组件卸载的时候,会执行下面的方法,来清除之前的副作用
        return function cleanup() {
          ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
        };
      });
    
      if (isOnline === null) {
        return 'Loading...';
      }
      return isOnline ? 'Online' : 'Offline';
    }
    

    你也可以使用多个 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);
        };
      });
      
      // ...
      
    }
    

    使用class 来写react组件的时候,我们一般会从props 读取了信息的时候,当prop 发生变化,我们需要在componentDidUpdate 里面去处理:

     componentDidMount() {
        ChatAPI.subscribeToFriendStatus(
          this.props.friend.id,
          this.handleStatusChange
        );
      }
    
      componentDidUpdate(prevProps) {
        // 取消订阅之前的 friend.id
        ChatAPI.unsubscribeFromFriendStatus(
          prevProps.friend.id,
          this.handleStatusChange
        );
        // 订阅新的 friend.id
        ChatAPI.subscribeToFriendStatus(
          this.props.friend.id,
          this.handleStatusChange
        );
      }
    
      componentWillUnmount() {
        ChatAPI.unsubscribeFromFriendStatus(
          this.props.friend.id,
          this.handleStatusChange
        );
      }
    

    componentDidUpdate 里面的处理,这一步经常被遗忘,是 React 应用中常见的 bug 来源。

    如果我们使用Hook,可以很好的避免这个问题,且不需要额外的处理。




  • 通过跳过 Effect 进行性能优化
    useEffect的第二个参数为可选,其作用为控制某些值变化后才执行:

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

    当我们期望的值没有发生变化的时候,不会执行useEffect里面的逻辑。




注意在单个组件中使用多个 State Hook 或 Effect Hook的时候,一定要注意其顺序要一一对应,这是React内部State 和 Effect 匹配的唯一依据

// ------------
// 首次渲染
// ------------
useState('Mary')           // 1. 使用 'Mary' 初始化变量名为 name 的 state
useEffect(persistForm)     // 2. 添加 effect 以保存 form 操作
useState('Poppins')        // 3. 使用 'Poppins' 初始化变量名为 surname 的 state
useEffect(updateTitle)     // 4. 添加 effect 以更新标题

// -------------
// 二次渲染
// -------------
useState('Mary')           // 1. 读取变量名为 name 的 state(参数被忽略)
useEffect(persistForm)     // 2. 替换保存 form 的 effect
useState('Poppins')        // 3. 读取变量名为 surname 的 state(参数被忽略)
useEffect(updateTitle)     // 4. 替换更新标题的 effect

Hook 的使用规则

  1. 只在最顶层使用 Hook
    不要在循环,条件或嵌套函数中调用 Hook

  2. 只在 React 函数中调用 Hook
    不要在普通的 JavaScript 函数中调用 Hook

官方推荐使用eslint-plugin-react-hooks强行检查,避免因使用不当产生的bug。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值