最近的新项目全部采用的是react hooks,说说hooks吧
本文地址: ()
avatar
作者: FeRookie 类型: 原创
更新时间:2022-01-26 阅读:561

需求描述:

在本项目之前,公司项目均采用的是Vue技术栈,根据公司,前端组以及个人需求等最终得出技术栈将慢慢迁移到React

技术栈:

本项目仅采用了react hooks 以及 fetch.js 还有很多第三方库包,未曾涉及到redux

react hooks:

虽说现在网上有很多关于react hooks的一些文章,但是我还是想写写,一呢是想加深印象,二呢是想知道自己理解的东西和别人理解的不一样的地方。 首先我们来理解一下什么是hooks: 相信大家在react hooks发布之前都会使用到class components(类组件), 以及 function components(无状态组件)

// 类组件
class App extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            name: 'dengpeng'
        }
    }
    render() {
        return (<Foo name={this.state.name}/>);
    }
}

// 无状态组件
function Foo(props) {
    const { name } = props;
    return (<div>{name}</div>);
}

在之前function components(无状态组件)里面是无法法使用 react 生命周期的,所以在Hooks发布后这类组件,便被称为“函数组件(FC)”了,因为可以在里面使用Hooks了,比如:

function Bar() {
    // hooks
    const [name, setName] = useState('dengpeng');
    return (<div>{name}</div>);
}

那么Hooks到底是什么呢? Hooks 就是一个特殊的钩子函数,用于将react的特性加入到FC里来,比如useState,他就是允许在React FC中添加state的Hook。

  1. useState 这是react hooks最最常用的3大hooks之一 useState,那么他到底是什么呢? useState: 一呢声明了state变量以及操作state的方法,比如上面的例子。 useState参数:它接收一个参数,就是声明的这个state的初始值 useState返回值:他返回一个数组,数组里有2个对象,一呢是state变量,二呢就是state方法,如果你要修改state值,就会使用这个方法。 比如:

    // 读取state数据
    const [name, setName] = useState('dengpeng');
    return <div>读取name: {name}</div>;
    // 修改state数据
    <button onClick={() => setName('caipeiyi')} >修改name</button>;
  2. useEffect 这是react hooks最最常用的3大hooks之一 useEffect,那么他到底是什么呢? 相传useEffect 结合了类组件的3大生命周期集一身,componentDidUpdate(cDU), componentDidMount(cDM), componentWillUnmount(cWU),他为何如此之吊。我也不知道!!这也许就是react魅力之处吧,至从16.8更新以来,惊喜不断呀!!!!! 在之前类组件的时候,常见操作组件的方式需要清除某些东西cWU和不需要清除cDU,那么useEffect如何实现这个功能的呢,源码我们就不看了,看个例子就行了。

     // exmp1
     useEffect(() => {
         document.title = '邓鹏博客'
     }, [])
    
     // exmp2
     useEffect(() => {
         const query = location.search.query;
         document.title = '邓鹏博客' + query
     }, [query])
    
     // exmp3
     useEffect(() => {
         document.title = '邓鹏博客'
     })
     useEffect(() => {
         let timer = setInterval(() => {
             console.log(11111);
         }, 1000)
         return () => {
             clearInterval(timer);
         }
     })

    如上有3个例子:useEffect 可接收2个参数,其中第一个参数是一个函数(required),第二个参数(非必要参数)就非常厉害了,是一个依赖数组。 exmp1: 第二个参数是一个空数组,代表着当前useEffect 不需要依赖某项而发生变化,意味着只会执行一次,就是cDM exmp2: 第二个参数易依赖于query,代表着当前仅当query值发生变化的时候,useEffect的第一个参数函数才会重新执行一次,就是cDU; exmp3: 第二个参数被省略了,代表着只要当前组件的任意项,发生变化则该函数都会执行一次(最好不要这样) exmp4: 该例子不是看参数是什么,是看第一个参数函数的return,返回一个函数,该函数就是在组件卸载的时候需要清除的东西, 就是cWU;

  3. useContext 这是react hooks最最常用的3大hooks之一 useContext,那么他到底是什么呢? 他就是react 关联上下文的一个Hooks,旨在便捷组件内部通信,不用组件之间层级传递props 在16.8之前,react是如何创建上下文,并如何使用上下文的呢?

     // app.js
     export const ThemeContext = React.createContext(themes.light);
     export default class App extends React.Component {
         const value = {name: 'dengpeng'}
         render() {
             return (
                 <ThemeContext.Provider value={value}>
                     <Container />
                 </ThemeContext.Provider>
             )
         }
     }
     // container.js 使用Consumer
     import { ThemeContext } from 'app.js'
     class Container extends React.Component {
         render() {
             return (
                 <ThemeContext.Consumer>
                     { value => (
                         <div>{value.name}</div>
                     ) }
                 </ThemeContext.Consumer>
             )
         }
     }
     // container.js 使用Hooks
     import React, {useContext} from 'react';
     import { ThemeContext } from 'app.js';
     function Container:FC = () => {
         const value = useContext(ThemeContext);
         return (
             <div>{value.name}</div>
         )
     }

    根据上面例子可以看出,使用Hooks 省略了ThemeContext.Consumer的包裹,并且也不用使用函数回调的方式,可以直接使用useContext获取context的数据。

提醒事项:

  1. useState为什么返回的是一个数组呢,而不是一个{}呢? 首先,返回的是数组意味着这里采用的是数组解构,就等价于 等号左边的变量名 可以自定义。 如果是{}那么里面的变量肯定是固定的,只有通过别名才能保持不一样,所以展示效果不太好,比如

     // 数组方式
     const fruitArray = useState('apple');
     // 等号作品可以随意取名
     const fruit = fruitArray(0);
     const setFruit = fruitArray(1);
     // 所以数组解构
     const [fruit1, setFruit1] = useState('apple');
     const [fruit2, setFruit2] = useState('pear');
    
     // {}方式,对象解构方式
     const animalArray = useState('snake');
     const animal = animalArray['animal'];
     const setAnimal = animalArray['setAnimal'];
     // 对象解构
     const { animal: animal1, setAnimal: setAnimal1 } = useState('snake');
     const { animal: animal2, setAnimal: setAnimal2 } = useState('snake');
    
     // 从上面看来, 数组解构方式更加直观一点,而对象解构相对麻烦一点
  2. 在使用useEffect的时候,官网推荐启用 eslint-plugin-react-hooks 中的 exhaustive-deps 规则。此规则会在添加错误依赖时发出警告并给出修复建议。但是很多时候我们用到了不需要监听的依赖,启用后就会报错,应该如何解决呢

     const [count, setCount] = useState(5)
     useEffect(() => {
         const query = location.search.query;
         document.title = '邓鹏博客' + count + query;
         // 在这里的依赖项正常情况下是[query, count],但是我们只需要监听到count变化才变化title,那怎么办呢
         // 第一个办法是将query声明在effect外部
         // 第二个办法是增加检测依赖项规则的忽略片段
         // // eslint-disable-next-line react-hooks/exhaustive-deps (当然 官方是不推荐的哈)
     }, [count])

    总之:react hooks更加接近函数编程,更加清晰的将React分成2个阶段,commit阶段和render阶段。后续会继续介绍react其他hooks。 博客首页 查看更多文章。 欢迎大家留言,给出意见!