,

Hooks

Hooks 基本介绍 Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下…

Hooks 基本介绍

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

Hooks 的出现,首先能解决如下的一些问题:

  • 告别令人疑惑的生命周期
    • 例如下面的例子,相同的代码在不同的生命周期中存在了两份
import React from "react";

// 类组件
class App extends React.Component {

 constructor() {
   super();
   this.state = {
     count : 0
  }
}

 componentDidMount(){
   document.title = `你点击了${this.state.count}次`;
}

 componentDidUpdate(){
   document.title = `你点击了${this.state.count}次`;
}

 render() {
   return (
     <div>
       <p>You clicked {this.state.count} times</p>
       <button onClick={() => this.setState({ count: this.state.count + 1 })}>
        Click me
       </button>
     </div>
  )
}
}

export default App;
  • 告别类组件中烦人的 this
    • 在类组件中,会存在 this 的指向问题,例如在事件处理函数中,不能直接通过 this 获取组件实例,需要修改 this 指向
  • 告别繁重的类组件,回归前端程序员更加熟悉的函数

另外,Hooks 的出现,还有更加重要的一个信号,那就是整个 React 思想上面的转变,从“面向对象”的思想开始转为“函数式编程”的思想。这是编程范式上面的转变。

Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则:

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

useStateuseEffect

useState 包含以下的知识点:

  • 基本使用
import { useState } from 'react';

function App(props) {

 let [count, setCount] = useState(0);

 function clickhandle(){
   setCount(++count);
}

 return (
   <div>
     <div>{count}</div>
     <button onClick={clickhandle}>+1</button>
   </div>
);
}

export default App;
  • 声明多个 state 状态
import { useState } from 'react';

function App(props) {

 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 包含以下知识点:

副作用的概念

  • 纯函数:一个确切的参数在你的函数中运行后,一定能得到一个确切的值
  • 如果一个函数中,存在副作用,那么我们就称该函数不是一个纯函数,所谓副作用,就是指函数的结果是不可控,不可预期。
  • 常见的副作用有发送网络请求、添加一些监听的注册和取消注册,手动修改 DOM,以前我们是将这些副作用写在生命周期钩子函数里面,现在就可以书写在 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;
  • 执行清理工作
import { useState, useEffect } from 'react';

function App() {

 let [count, setCount] = useState(0);

 useEffect(()=>{
   // 书写你要执行的副作用,会在组件渲染完成后执行
   const stopTimer = setInterval(()=>{
     console.log("Hello");
  },1000)  

   // console.log("副作用函数执行了");
   // 在 useEffect 中,可以返回一个函数,该函数我们称之为清理函数(一般就是做一些清理操作)
   // 该函数会在下一次渲染之后,但是在执行副作用操作之前执行
   return ()=>{
     // console.log("清理函数执行了");
     clearInterval(stopTimer);
  }
});


 function clickhandle() {
   setCount(++count);
}

 return (
   <div>
     <div>你点击了{count}次</div>
     <button onClick={clickhandle}>+1</button>
   </div>
);
}

export default App;
  • 副作用的依赖
    • 目前,我们的副作用函数,每次重新渲染后,都会重新执行,有些时候我们是需要设置依赖项,传递第二个参数,第二个参数为一个依赖数组
import { useState, useEffect } from 'react';

function App() {

  let [count1, setCount1] = useState(0);
  let [count2, setCount2] = useState(0);
  let [count3, setCount3] = useState(0);

  useEffect(()=>{
    console.log("执行副作用函数");
  },[count1]);

  return (
    <div>
      <div>count1:{count1}</div>
      <div>count2:{count2}</div>
      <div>count3:{count3}</div>
      <button onClick={()=>setCount1(++count1)}>+1</button>
      <button onClick={()=>setCount2(++count2)}>+1</button>
      <button onClick={()=>setCount3(++count3)}>+1</button>
    </div>
  );
}

export default App;

如果想要副作用只执行一次,传递第二个参数为一个空数组

useEffect(()=>{
  console.log("执行副作用函数");
},[]);

自定义 Hook

除了使用官方内置的 Hook,我们还可以自定义 Hook,自定义 Hook 的本质其实就是函数,但是和普通函数还是有一些区别,主要体现在以下两个点:

  • 自定义 Hook 能够调用诸如 useStateuseRef 等,普通函数则不能。由此可以通过内置的 Hooks 获得 Fiber 的访问方式,可以实现在组件级别存储数据的方案等。
  • 自定义 Hooks 需要以 use 开头,普通函数则没有这个限制。使用 use 开头并不是一个语法或者一个强制性的方案,更像是一个约定。
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;

Previous Post

Next Post

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About the Author

每个人都有自己得时区,在自己得时区里,一切都是准时的。

BlockSpare — News, Magazine and Blog Addons for (Gutenberg) Block Editor