深入理解React Hooks:从基础到自定义

110 阅读3分钟

引言

React Hooks是React 16.8版本引入的一项新特性,它允许我们在不编写类组件的情况下使用state和其他React特性。Hooks的出现不仅仅是React API的一次扩展,更是React编程范式从面向对象向函数式编程转变的一个重要标志。

Hooks基本介绍

Hooks解决了什么问题?

  1. 告别生命周期的困惑:在类组件中,相同的逻辑可能需要在多个生命周期方法中重复编写,而Hooks使得我们可以在函数组件中以更简洁的方式处理这些逻辑。
  2. 告别this的指向问题:在类组件中,this的指向问题常常导致开发者需要额外的绑定操作,而Hooks使得我们不再需要担心这个问题。
  3. 回归函数式编程:Hooks鼓励我们使用函数式编程范式,这与面向对象编程范式形成对比,函数式编程更关注于“做什么”而不是“怎么做”。

编程范式的转变

  • 命令式编程:告诉计算机怎么做,需要指明每一个步骤,如面向过程和面向对象编程。
  • 声明式编程:告诉计算机要什么,如函数式编程和DSL(领域专用语言,如HTML、CSS、SQL)。

随着项目复杂度的增加,声明式编程因其简洁性和可维护性逐渐受到青睐。

Hooks的使用规则

  • Hooks只能在函数组件的最外层调用,不能在循环、条件判断或子函数中调用。
  • Hooks只能在React的函数组件中调用,不能在其他JavaScript函数中调用。

useState和useEffect

useState

useState是React内置的Hook之一,用于在函数组件中添加状态。

import { useState } from 'react';
​
function App() {
  let [count, setCount] = useState(0);
​
  function clickHandle() {
    setCount(++count);
  }
​
  return (
    <div>
      <div>{count}</div>
      <button onClick={clickHandle}>+1</button>
    </div>
  );
}
​
export default App;

useState也支持声明多个state状态。

import { useState } from 'react';
​
function App() {
  let [age, setAge] = useState(18);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: '学习 Hook' }]);
​
  function clickHandle() {
    setAge(++age);
  }
​
  return (
    <div>
      <div>年龄:{age}</div>
      <div>水果:{fruit}</div>
      <div>待办事项:{todos[0].text}</div>
      <button onClick={clickHandle}>+1</button>
    </div>
  );
}
​
export default App;

useEffect

useEffect是处理副作用的Hook,它允许我们在函数组件中执行副作用操作。

import { useState, useEffect } from 'react';
​
function App() {
  let [count, setCount] = useState(0);
​
  useEffect(() => {
    document.title = `你点击了${count}次`;
  });
​
  function clickHandle() {
    setCount(++count);
  }
​
  return (
    <div>
      <div>你点击了{count}次</div>
      <button onClick={clickHandle}>+1</button>
    </div>
  );
}
​
export default App;

useEffect也支持执行清理工作和依赖项的管理。

import { useState, useEffect } from 'react';
​
function App() {
  let [count, setCount] = useState(0);
​
  useEffect(() => {
    const stopTimer = setInterval(() => {
      console.log("Hello");
    }, 1000);
​
    return () => {
      clearInterval(stopTimer);
    };
  });
​
  function clickHandle() {
    setCount(++count);
  }
​
  return (
    <div>
      <div>你点击了{count}次</div>
      <button onClick={clickHandle}>+1</button>
    </div>
  );
}
​
export default App;

自定义Hook

自定义Hook允许我们封装组件逻辑,使其可以在多个组件间复用。

import { useState } from 'react';
import useMyBook from "./useMyBook";
​
function App() {
  const { bookName, setBookName } = useMyBook();
  const [value, setValue] = useState("");
​
  function changeHandle(e) {
    setValue(e.target.value);
  }
​
  function clickHandle() {
    setBookName(value);
  }
​
  return (
    <div>
      <div>{bookName}</div>
      <input type="text" value={value} onChange={changeHandle} />
      <button onClick={clickHandle}>确定</button>
    </div>
  );
}
​
export default App;
import { useState } from "react";
​
function useMyBook() {
  const [bookName, setBookName] = useState("React 学习");
  return {
    bookName, setBookName
  };
}
​
export default useMyBook;

结语

Hooks为我们提供了一种新的方式来使用React特性,它不仅简化了代码,还促进了函数式编程范式的普及。通过自定义Hooks,我们可以进一步封装和复用逻辑,提高代码的可维护性和可读性。

参考链接

关于面向对象编程与函数式编程的对比,推荐阅读以下文章,以获得更深入的理解:

Functional Programming vs OOP