react

✍️ Tangxt ⏳ 2021-03-24 🏷️ 函数组件

函数组件

★函数组件比 class 组件简单

1)函数组件的创建方式

创建方式

话说,函数组件能替代 Class 组件吗?

函数组件

这是完全可以的!

可我们为什么要用函数组件代替 Class 组件呢? -> 因为简洁呀!

2)对比类组件函数组件实现 +1

1、class 组件

class

2、函数组件

函数组件

3、小结

对比函数组件和类组件:

  1. class 有this
  2. 函数消除了 this
  3. 写法上函数简单
  4. 功能上 -> 请看后边

3)函数组件代替 class 组件

代替 class 组件

useEffect:函数式编程的专有名词,主要解决生命周期问题(回答面试:解决副作用问题) -> 面试一套回答,开发一套回答!这得看面试官的水平如何!

★函数组件模拟生命周期

1)componentDidMount

模拟第一次渲染

第一次渲染

我们知道这个componentDidMount在类里边是只执行一次的

如果我们这样模拟(直接写):

模拟

如果你写成setN(n)这样,是不会执行 Test7 的,因为数据没变!

如果我们用了userEffect(()=>{})这样模拟,这跟「直接写」是差不多的!

useEffect

但是,如果给useEffect加了第二个参数(指明在什么情况下去运行这个函数),如用空数组做第二个参数,就可以模拟第一次渲染的钩子:

console.log(n)
useEffect(()=>{
  console.log(n)
},[])

加数组

关于这个警告:reactjs - How to fix missing dependency warning when using useEffect React Hook? - Stack Overflow

2)componentDidUpdate(自定义 Hook)

模拟数据更新执行函数

更新后执行

数组有值

如果多个数据,只有监听了的数据变化才会执行:

监听两个

如果是所有 state 数据,可以直接不写,意思就是任何一个 state 变化都会执行(开始的那样,即不带第二个参数):

监听所有的 state

💡:话说,如何消除第一次变化的执行?

姿势 1:加一层useState计数

姿势 1

这种姿势很麻烦,还要额外声明一个东西!

姿势 2:通过函数组合(一定是use开头的函数名返回这个计数的数据)

姿势 2

把这个东西从函数组件里边抽离出来,直接封装成:

useCount

这个做法,相当于重写了一个功能更完善(排除第一次变化)的useEffect

目前这个代码,是有问题的,看到那个没有?这意味着fn多次执行了:

自定义 hooks

一个疑问:

疑问

我测试了一下,发现这是代码缓存的缘故,我把使用useUpdate的第二个参数改成是[n]这样,就得到了我想要的效果了!

为什么会执行两遍? -> useUpdate它搞得鬼!

默认的useEffect,不会在n变化的时候执行两遍Test8

useEffect

目前的问题是:

为什么管第二个参数叫「依赖项」? -> 因为第一个参数是否执行,依赖第二项的变化与否!

为什么第二个参数为[]就只会执行一遍fn? -> 因为fn不依赖任何变量,无论那些变量怎么变,fn的执行结果都不会变,既然执行结果都不变了,再执行也就没有任何意义了,所以只执行一遍fn就足够了!


执行两遍如何解决?

我测试了一下,关闭严格模式也无法解决! -> 打包后也是执行两遍!

参考:为什么 react 的函数组件每次渲染执行两次?- 知乎

既然无法解决,我就认为这个useUpdate写得并不好,于是在网上找到了模拟componentDidUpdate的另一种写法:

另一种写法

➹:使用 React Hooks 模拟生命周期


可以把useUpdate封装成一个文件 -> 这就叫做「自定义 Hook

自定义 hook

useUpdate就是我们第一个自定义 Hook!

3)componentWillUnmount

模拟消失

componentWillUnmount

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

const Fa = () => {
  const [sonVisible, setSonVisible] = useState(true);
  const hide = () => {
    setSonVisible(false);
  };
  const show = () => {
    setSonVisible(true);
  };
  return (
    <div>
      {sonVisible ? (
        <button onClick={hide}>hide</button>
      ) : (
        <button onClick={show}>show</button>
      )}
      {sonVisible ? <Test9/> : null}
    </div>
  );
};

const Test9 = () => {
  const [n, setN] = useState(0);
  const addN = () => {
    setN(n + 1);
  };

  useEffect(() => {
    console.log('Son 第一次渲染')
    return () => {
      console.log('组件 Son 要死了')
    }
  },[])
  console.log(`Son render 第${n + 1}次`);
  return (
    <div>
      n: {n}
      <button onClick={addN}>n+1</button>
    </div>
  );
};

export default Fa;

效果:

效果

要加[]参数,不然,子组件状态发生变化时,那个 console.log('组件 Son 要死了') 也会执行!

解析:


可以看到,React 它有一个特点,那就是 -> 所有东西都可以通过函数组合来实现

4)其它生命周期怎么模拟

其它生命周期的模拟

★了解更多

➹:轻松学会 React 钩子:以 useEffect() 为例 - 阮一峰的网络日志

➹:React Hooks 入门教程 - 阮一峰的网络日志