Hooks 出了有段时间了,不知盆友们有在项目中开始使用了吗❓如果还没了解的童鞋,可以瞧瞧这篇文章,对比看下三大基础 Hooks 和传统 class 组件的区别和用法吧????我们所指的三个基础 Hooks 是:useState 在函数式组件内维护 stateuseEffect 函数式组件内有副作用的调用与 componentDidMount、componentDidUpdate 类似但又有所区别useContext 监听 provider 更新变化useStateuseState 允许我们在函数式组件中维护 state,传统的做法需要使用类组件。举个例子????,我们需要一个输入框,随着输入框内容的改变,组件内部的 label 标签显示的内容也同时改变。下面是两种不同的写法:不使用 useState:import React from “react”;// 1export class ClassTest extends React.Component { // 2 state = { username: this.props.initialState } // 3 changeUserName(val) { this.setState({ username: val }) } // 4 render() { return ( <div> <label style={{ display: ‘block’ }} htmlFor=“username”>username: {this.state.username}</label> <input type=“text” name=“username” onChange={e => this.changeUserName(e.target.value)} /> </div> ) }}我们需要定义一个类并从 React.Component 处继承还需要初始化一个 state初始化改变 state 的方法最后还要使用 render 函数返回 JSX✅使用 useState:// 1import React, { useState } from “react”;export function UseStateTest({ initialState }) { // 2 let [username, changeUserName] = useState(initialState) // 3 return ( <div> <label style={{ display: ‘block’ }} htmlFor=“username”>username: {username}</label> <input type=“text” name=“username” onChange={e => changeUserName(e.target.value)} /> </div> )}在父组件中使用:import React from “react”;// 引入组件import { UseStateTest } from ‘./components/UseStateTest’// 4const App = () => ( <div> <UseStateTest initialState={‘initial value’} /> </div>)export default App;需要从 react 中引入 useState 这个????使用 useState 方法,接收一个初始化参数,定义 state 变量,以及改变 state 的方法在需要使用的地方直接使用 state 这个变量即可,增加事件处理函数触发改变 state 的方法在父组件中调用,通过 props 传递 initialState 初始化值用 useState 方法替换掉原有的 class 不仅性能会有所提升,而且可以看到代码量减少很多,并且不再需要使用 this,所以能够维护 state 的函数式组件真的很好用????class classTest extends React.Components {} ???? function UseStateTest(props) {} 函数式组件写法this.state.username ???? username 使用 state 不需要 thisthis.setState({ username: ’’ }) ???? changeUserName(’’) 改变 state 也不需要书写 setState 方法文档说明:https://zh-hans.reactjs.org/d…useEffectuseEffect 是专门用来处理副作用的,获取数据、创建订阅、手动更改 DOM 等这都是副作用。你可以想象它是 componentDidMount 和 componentDidUpdate 及 componentWillUnmount 的结合。举个例子????????,比方说我们创建一个 div 标签,每当点击就会发送 http 请求并将页面 title 改为对应的数值:import React from ‘react’// 1import { useState, useEffect } from ‘react’export function UseEffectTest() { let [msg, changeMsg] = useState(’loading…’) // 2 async function getData(url) { // 获取 json 数据 return await fetch(url).then(d => d.json()) } // 3 async function handleClick() { // 点击事件改变 state let data = await getData(‘https://httpbin.org/uuid').then(d => d.uuid) changeMsg(data) } // 4 useEffect(() => { // 副作用 document.title = msg }) return ( <div onClick={() => handleClick()}>{msg}</div> )}首先从 react 中引入 useEffect ????然后创建获取数据的 getData 方法创建事件处理函数 handleClick使用 useEffect 处理副作用:改变页面的 title如果使用传统的类组件的写法:import React from ‘react’// 1export class ClassTest extends React.Component { // 2 state = { msg: ’loading…’ } // 3 async getData(url) { // 获取 json 数据 return await fetch(url).then(d => d.json()) } handleClick = async () => { // 点击事件改变 state let data = await this.getData(‘https://httpbin.org/uuid').then(d => d.uuid) this.setState({ msg: data }) } // 4 componentDidMount() { document.title = this.state.msg } componentDidUpdate() { document.title = this.state.msg } // 5 render() { return ( <div onClick={this.handleClick}>{this.state.msg}</div> ) }}首先创建类 ClassTest初始化 state定义获取数据方法和事件处理函数在 componentDidMount 和 componentDidUpdate 阶段改变 document.title最后通过 render 函数渲染这一堆东西写完人都睡着了????使用 useEffect 不仅去掉了部分不必要的东西,而且合并了 componentDidMount 和 componentDidUpdate 方法,其中的代码只需要写一遍。????第一次渲染和每次更新之后都会触发这个钩子,如果需要手动修改自定义触发规则见文档:https://zh-hans.reactjs.org/d…另外,官网还给了一个订阅清除订阅的例子:使用 useEffect 直接 return 一个函数即可:返回的函数是选填的,可以使用也可以不使用:文档:https://zh-hans.reactjs.org/d…比方说我们使用 useEffect 来解绑事件处理函数:useEffect(() => { window.addEventListener(‘keydown’, handleKeydown); return () => { window.removeEventListener(‘keydown’, handleKeydown); }})useContextuseContext 的最大的改变是可以在使用 Consumer 的时候不必在包裹 Children 了,比方说我们先创建一个上下文,这个上下文里头有一个名为 username 的 state,以及一个修改 username 的方法 handleChangeUsername创建上下文不使用 useState:不使用 state hooks 的代码如下:import React, { createContext } from ‘react’// 1. 使用 createContext 创建上下文export const UserContext = new createContext()// 2. 创建 Providerexport class UserProvider extends React.Component { handleChangeUsername = (val) => { this.setState({ username: val }) } state = { username: ‘’, handleChangeUsername: this.handleChangeUsername } render() { return ( <UserContext.Provider value={this.state}> {this.props.children} </UserContext.Provider> ) }}// 3. 创建 Consumerexport const UserConsumer = UserContext.Consumer看看我们做了什么:首先我们使用 createContext 创建了上下文然后我们创建 Provider;里头定义了 handleChangeUsername 方法和 username 的 state,并返回一个包裹 this.props.children 的 Provider最后我们再返回 UserContext.Consumer代码比较冗长,可以使用上文提到的 useState 对其进行精简:✅使用 useState:使用 state hooks:import React, { createContext, useState } from ‘react’// 1. 使用 createContext 创建上下文export const UserContext = new createContext()// 2. 创建 Providerexport const UserProvider = props => { let [username, handleChangeUsername] = useState(’’) return ( <UserContext.Provider value={{username, handleChangeUsername}}> {props.children} </UserContext.Provider> )}// 3. 创建 Consumerexport const UserConsumer = UserContext.Consumer使用 useState 创建上下文更加简练。使用上下文上下文定义完毕后,我们再来看使用 useContext 和不使用 useContext 的区别是啥????:不使用 useContext:import React from “react”;import { UserConsumer, UserProvider } from ‘./UserContext’const Pannel = () => ( <UserConsumer> {/* 不使用 useContext 需要调用 Consumer 包裹 children */} {({ username, handleChangeUsername }) => ( <div> <div>user: {username}</div> <input onChange={e => handleChangeUsername(e.target.value)} /> </div> )} </UserConsumer>)const Form = () => <Pannel></Pannel>const App = () => ( <div> <UserProvider> <Form></Form> </UserProvider> </div>)export default App;✅使用 useContext:只需要引入 UserContext,使用 useContext 方法即可:import React, { useContext } from “react”; // 1import { UserProvider, UserContext } from ‘./UserContext’ // 2const Pannel = () => { const { username, handleChangeUsername } = useContext(UserContext) // 3 return ( <div> <div>user: {username}</div> <input onChange={e => handleChangeUsername(e.target.value)} /> </div> )}const Form = () => <Pannel></Pannel>// 4const App = () => ( <div> <UserProvider> <Form></Form> </UserProvider> </div>)export default App;看看做了啥:首先第一步引入useContext然后引入 UserProvider 以及上下文 UserContext再需要使用的组件中调用 useContext 方法获取 state当然前提是要在父组件中使用 UserProvider 嵌套主 children这样通过 useContext 和 useState 就重构完毕了,看起来代码又少了不少????以上,三个基础的 Hooks 入门就讲解完毕了,上手就是这样,函数式组件和 Hooks 配合使用真的非常爽⛄参考:https://codeburst.io/quick-in…https://reactjs.org/docs/hook