Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
React 大概有两种形式,Class/Function Component 和新加入的 Hook。其中,多数的 React 代码示例使用的都是 Class Component。最近在做毕设的时候,接触到了一个使用 Hook 的模板,因为之前看的文档基本都是 Class Component,前端接触的又不多,一度以为这是用 Function Component 写的,因为 Function Component 的资料少,还重写成了 Class。研究了以下文档 Hook 部分,才发现原来模板用的是 Hook。
注意:React 16.8.0 是第一个支持 Hook 的版本。升级时,请注意更新所有的 package,包括 React DOM。 React Native 从 0.59 版本开始支持 Hook。
Class Component
Class Component 大概长这样,整体的结构分为 state,componentDidMount 和 render 三部分。以下为一个简单示例。
import React, { Component } from "react";
import { Grid } from "@material-ui/core";
import MUIDataTable from "mui-datatables";
import axios from "axios";
export default class Tables extends Component {
state = {
datatableData: [],
columns: [
{
name: "id",
label: "ID",
options: {
display: "excluded",
},
},
{ name: "username", label: "用户名" },
{ name: "email", label: "邮箱" },
{ name: "phone", label: "电话" },
{ name: "createdDate", label: "注册日期" },
{ name: "isActivated", label: "状态" },
],
};
componentDidMount() {
axios.post("/User/searchAllUserList", {}).then((res) => {
if (res.status === 200 && Object.keys(res.request.response).length > 0) {
const datatableData = JSON.parse(res.request.response);
this.setState({ datatableData });
}
});
}
render() {
return (
<>
<Grid container spacing={4}>
<Grid item xs={12}>
<MUIDataTable
title="用户列表"
data={this.state.datatableData}
columns={this.state.columns}
options=
/>
</Grid>
</Grid>
</>
);
}
}
Hook
Hook 的写法虽然也是类似的三部分,但是更加灵活。相同意义的部件用 Hook 写长这样。
import React, { useState, useEffect } from "react";
import { Grid } from "@material-ui/core";
import MUIDataTable from "mui-datatables";
import axios from "axios";
export default function Tables(props) {
var [datatableData, setdatatableData] = useState([]);
var [columns, setColumns] = useState([
{
name: "id",
label: "ID",
options: {
display: "excluded",
},
},
{ name: "username", label: "用户名" },
{ name: "email", label: "邮箱" },
{ name: "phone", label: "电话" },
{ name: "createdDate", label: "注册日期" },
{ name: "isActivated", label: "状态" },
]);
useEffect(() => {
axios.post("/User/searchAllUserList", {}).then((res) => {
if (res.status === 200 && Object.keys(res.request.response).length > 0) {
const data = JSON.parse(res.request.response);
setdatatableData(data);
}
});
}, []);
return (
<>
<Grid container spacing={4}>
<Grid item xs={12}>
<MUIDataTable
title="用户列表"
data={this.state.datatableData}
columns={this.state.columns}
options=
/>
</Grid>
</Grid>
</>
);
}
Hook的意义
Hook可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。比如可以通过set完成变量赋值,通过useEffect的[]完成数据更新。基本上Class能实现的,Hook也能实现。
根据 Hook简介-动机 中的描述:
由 providers,consumers,高阶组件,render props 等其他抽象层组成的组件会形成“嵌套地狱”。
同一个 componentDidMount 中可能也包含很多其它的逻辑,在多数情况下,不可能将组件拆分为更小的粒度,使得复用变得更加困难。
class 是学习 React 的一大屏障.即便在有经验的 React 开发者之间,对于函数组件与 class 组件的差异也存在分歧。
Hook的import包含了React和useState, useEffect两部分,而Component包含React和Component。useState是用来做初始状态赋值的,useEffect是来做数据更新的。
其中 useEffect(() => {}, []);
的 []
中的内容为动态更新的变量内容(为空的话就不更新)。React会根据 []
中的数据是否更新,来判断是否渲染新的内容(会一直发送axios请求)。如果不写 []
的话,就会一直执行useEffect的内容,此时网页应该会卡飞。
如果你在编写函数组件并意识到需要向其添加一些 state,以前的做法是必须将其转化为 class。现在你可以在现有的函数组件中使用 Hook。
不过我目前只有体会到Hook的使用方便,例如把function形式代码改写为Hook变得更加容易。对于嵌套和状态,有遇过一次使用多个react(把hook改写为class),但是暂时还没有什么理解。当下只是觉得很郁闷,查了半天也不太清楚要怎么改错。Hook对我来说就是一种更好的Class,可以很轻易完成新的模块的加入,并且不用担心会出问题。
参考资料: