啥是Hooks?为啥要用Hooks?Hooks该怎么用?像是Vue中的什么?React Hooks的使用姿势(上)

Hi!这里是在学习React的JustHappy,相信你和我一样,对React的Hooks早有耳闻,可以说Hooks的出现使得React的编写方式有了革命性的飞跃,更加接近原生JS、更加灵活、复用性更高......所以话不多说,我们开始吧!

同样我们也会对比着Vue去讲,一共要聊8个常用的Hooks,本篇我们先聊4个吧

什么是Hooks?为什么需要Hooks

React Hooks 是 React 16.8 版本引入的一种特性,它允许你在函数组件中使用状态和其他 React 特性,而无需将其转换为类组件。在这之前React主流的组件编写方式是类组件而不是函数式组件,

常用Hook怎么用?

当你需要定义一个响应式数据 ------ useState

首先我们明确一个基本概念!在 Web 开发中,什么是响应式数据(Reactive Data)?

只有一句话,视图层(DOM / UI)会随着状态的变化自动更新。

Vue和React中是如何使用的?

在Vue中当你需要定义一个响应式数据的时候,我们通常会想到ref或者reactive,如果我们在Vue的template中去写一个数据,并希望这个数据变化的时候在渲染层去更新这个数据,那使用ref或者reactive简直是无脑的操作,就像下面这样。

html 复制代码
<template>
  <div>
    <p>点击了 {{ count }} 次</p>
    <button @click="count++">点击</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

那么?在react中我们该怎么做呢? 那就是使用useState,同样的操作会像下面这样

js 复制代码
import { useState } from 'react';

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

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

当你需要有个"副作用" ------ useEffect / useLayoutEffect

所谓"副作用",就是副带的作用,比如说吃地瓜多的副作用是会放屁,当然副作用不一定是坏的是吧🤪🤪

在 Vue 里面,其实副作用我们也经常在搞,比如:

  • mounted 里面去请求接口;
  • watch 里监听某个变量变化后做点事情;
  • updated 里拿到更新后的 DOM 节点去干点什么;

而到了 React 里,就把这些副作用统一通过 useEffect(或者更极端一点,用 useLayoutEffect)来处理了。

你可以简单理解成,Vue 把副作用分散在生命周期和一些API里,React 则用一个钩子一把梭,收敛起来统一管理。

我们直接看看基本的代码使用吧

这是Vue中使用生命周期函数和watch实现的

html 复制代码
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="count++">+1</button>
  </div>
</template>

<script setup>
import { ref, watch, onMounted } from 'vue';

const count = ref(0);

onMounted(() => {
  console.log('组件挂载了,count 是', count.value);
});

watch(count, (newVal, oldVal) => {
  console.log('count 变化了:', oldVal, '=>', newVal);
});
</script>

这是React中使用useEffect实现的

jsx 复制代码
import { useState, useEffect } from 'react';

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

  useEffect(() => {
    console.log('组件挂载了,count 是', count);

    return () => {
      console.log('组件卸载或副作用清理');
    };
  }, []); // 空依赖数组,挂载时执行一次

  useEffect(() => {
    console.log('count 变化了:', count);
  }, [count]); // 依赖 count,每次 count 变化都会执行

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

export default Counter;

useEffect 和 useLayoutEffect 有什么区别呢?

其实他们在作用原理上只有一处不同,就是"副作用"执行的时机

  • useEffect:在浏览器完成布局与绘制之后才执行副作用函数(这个过程是不阻塞页面渲染的)

  • useLayoutEffect:在DOM变更后,浏览器绘制之前同步执行副作用函数(这个过程是阻塞渲染的)

关于这个我们也可以回顾一下Vue的生命周期,但是其边界还是有所差别

React useEffect 🆚 Vue mounted

其执行的时机是相同的,页面已经渲染,适合执行异步副作用,不影响用户看到的页面内容。

React useLayoutEffect 🆚 Vue mounted

useLayoutEffect中副作用执行的时机是对应 Vue中 mounted 之后,DOM已经被插入,但是未被渲染这一阶段,所以说useLayoutEffect同步执行副作用函数这个过程是阻塞渲染的

当你要获取一个DOM元素并对它进行....... ------ useRef

这里就非常简单了,这个操作的逻辑基本上和Vue中使用ref获取DOM一样,我们直接来看代码吧,我相信你也可以看得懂

  • Vue中
html 复制代码
<template>
  <div>
    <input ref="inputRef" placeholder="输入点啥..." />
    <button @click="focusInput">聚焦输入框</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const inputRef = ref(null)

const focusInput = () => {
  inputRef.value.focus()
}
</script>
  • React中
javascript 复制代码
import { useRef } from 'react'

export default function App() {
  const inputRef = useRef(null)

  const focusInput = () => {
    inputRef.current.focus()
  }

  return (
    <div>
      <input ref={inputRef} placeholder="输入点啥..." />
      <button onClick={focusInput}>聚焦输入框</button>
    </div>
  )
}
相关推荐
定栓4 分钟前
Webpack迁到Vite第五节:第三方库兼容
前端·webpack·node.js
NGINX开源社区11 分钟前
与我们交流:NGINX Gateway Fabric 与 NGINX Ingress Controller 社区会议
java·服务器·前端
ShineWinsu41 分钟前
对于CSS:弹性布局(Flexbox)的解析
前端·css·面试·浏览器·web·网页·弹性布局
山雀~44 分钟前
第5次百日救赎计划
前端
xiaogai_gai1 小时前
销售出库单同步实战:旺店通→金蝶云星空的单一策略深度拆解
大数据·前端·数据库
const_qiu1 小时前
第二章 2.6:初始化 NestJS 服务端 —— TypeScript 后端框架体验
前端·javascript·typescript
console.log('npc')2 小时前
[特殊字符] AI Agent 工作台前端实战教程 · 新手入门指南
前端·人工智能
gCode Teacher 格码致知2 小时前
前端教学2:ul标签的应用场合与经典案例
前端
const_qiu2 小时前
第 2.5 章 2.5.6:前端登录、Token 无感续签与路由守卫
java·前端·人工智能·状态模式