TS中使用hooks绑定antd组件(例:checkbox与checkboxgroup实现全选关联)

TS中使用hooks绑定antd组件(例:checkbox与checkboxgroup实现全选关联)

这篇文章是综合了ts+react16+hooks+antd的搬砖技术提升篇,对提升原理剖析能力及技术覆盖面的扩充非常有益。


扫码加微信前端二、三群(一群已满) :BAT大厂资深大牛定期推送面经与源码分析,各平台大牛优秀文章推荐,更有内推跳槽咨询、视频资源共享、学习资料文章pdf面经网盘资源等等福利。加入我们一起进步。

群内分享每日一题: 题目传送门

前端电子书大全: 电子书


Hooks为何要出现

生命周期钩子函数里的逻辑混乱
我们通常希望一个函数只做一件事情,但我们的生命周期钩子函数里通常同时做了很多事情。比如我们需要在 componentDidMount 中发起ajax请求获取数据,绑定一些事件监听等等。同时,有时候我们还需要在 componentDidUpdate 做一遍同样的事情。当项目变复杂后,这一块的代码也变得不那么直观。


classes使人困惑
我们用class来创建react组件时,还有一件很麻烦的事情,就是this的指向问题。为了保证this的指向正确,我们要经常写这样的代码: this.handleClick = this.handleClick.bind(this) ,或者是这样的代码: <button onClick={() => this.handleClick(e)}> 。一旦我们不小心忘了绑定this,各种bug就随之而来,很麻烦。

在ES的语言特性里,你在开发时不适应、甚觉繁琐的,hooks可以帮你 解决以下问题(优势)

1、无需继续考虑是写一个无状态组件(Function)还是有状态组件(Class) ---- 使用hooks,再也不需要写Class,所有组件都将是Function(形式为React.FC)

2、你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? —— 使用Hooks,生命周期钩子函数可以先丢一边了

3、你还在为组件中的this指向而晕头转向吗? —— Class都不再使用了,哪里还有this?你的人生第一次不再需要面对this。

hooks中最为重要的几个钩子函数useState,useEffect,useRefs,useContent等,参考简单例子:

import { useState } from 'react';
function Example() {
  const [count, setCount] = useState(0);
  return (
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>

Example 作为一个函数,但这个函数却有自己的状态(count),同时它还可以更新自己的状态(setCount)。除了 useState 这个hook外,还有很多别的hook,比如 useEffect 提供了类似于 componentDidMount 等生命周期钩子的功能, useContext 提供了上下文(context)的功能等等,全部都封装好了供你使用。

useState

useState是用来声明状态变量的方法函数,其中const[count, setCount]声明了一个状态变量count,把它的初始值设为0,同时提供了一个可以更改count的函数setCount(语法:es6解构赋值),读取状态再也不需要使用this.state.count这种形式了。

神奇的是setCount可以记录count之前的状态,参考:

同时react根据useState的出现顺序保证多个state之间保持独立状态(不会互相影响)

let showFruit = true;
function ExampleWithManyStates() {
  const [age, setAge] = useState(42);
  if(showFruit) {
    const [fruit, setFruit] = useState('banana');
    showFruit = false;
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  //第一次渲染
  useState(42);  //将age初始化为42
  useState('banana');  //将fruit初始化为banana
  useState([{ text: 'Learn Hooks' }]); //...
  //第二次渲染
  useState(42);  //读取状态变量age的值(这时候传的参数42直接被忽略)
  // useState('banana');  
  useState([{ text: 'Learn Hooks' }]); //读取到的却是状态变量fruit的值,导致报错

由此可见,react规定我们必须把hooks写在函数的最外层,不能写在if...else等条件语句当中,来确保hooks的执行顺序一致。

useEffect(异步执行)

Effect hooks的功能例子:

import { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);
  // 类似于componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 更新文档的标题
    document.title = `You clicked ${count} times`;
  return (
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>

react16不使用hooks,使用class实现一个有状态组件(与上方的进行比较较为复杂)

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  render() {
    return (
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>

有状态组件通常会产生很多的 副作用(side effect) ,比如发起ajax请求获取数据,添加一些监听的注册和取消注册,手动修改dom等等。我们之前都把这些副作用的函数写在生命周期函数钩子里,比如componentDidMount,componentDidUpdate和componentWillUnmount。而现在的 useEffect 就相当与这些声明周期函数钩子的 集合体, 以一抵三。

每个side effect都给一个effect hooks就不会像之前一样将状态都保存至didmount中了,同时还不用考虑在哪个周期中可以使用setState。


TS绑定hooks

我们所有的组件都可以使用以下形式

const JobModalForm: React.FC<FormComponentProps & JobModalFormPropsType> = props => {
  ......//各种方法
return(
  ......
export default Form.create()(JobModalForm)
//暴露出来供其他组件调用

我们按照上述模板写出一个可复用的自定义hook,当你的组件想用什么功能时,直接在组件里调用这个hook即可。形式与 高阶组件 的形式类似,数据传输结果又与 render props (渲染属性)类似。

其中 React.FC 为 React TypeScript 的一个函数组件类型。这部分内容和原书内容不一致,原书内容为 React.SFC ,函数组件SFC英文全称为“Stateless Function Components”,由于作者编写本书时hook还没成为正式标准,hooks的出现允许包含 state 和 React lifecycle。原来的英文缩写释义不能准确表达此意,所以使用 React.FC 来替换 React.SFC ,结合hooks后SFC存在即无意义。

使用 泛型 框定出函数组件的类型,更加严谨规范。

结合antd中我们可以使用

const { getFieldDecorator, setFieldsValue, getFieldValue, validateFields, resetFields } = props.form

中的props.form中的特定方法获取想要的内容。


使用useState将checkbox与checkboxgroup绑定

官方文档中使用React16针对多state关联checkbox与checkboxgroup,其中关注点为checkbox中的value,checkboxgroup中的checkedList,indeterminate为控制checkbox中全选状态的样式, 加入indeterminate后会出现三种样式,如何通过boolen控制三种样式的展示 ?借助checked的状态控制不同样式的内容

state = {
    checkedList: defaultCheckedList,
    indeterminate: true,
    checkAll: false
  onChange = checkedList => {
    this.setState({
      checkedList,
      indeterminate:
        !!checkedList.length && checkedList.length < plainOptions.length,
      checkAll: checkedList.length === plainOptions.length
  onCheckAllChange = e => {
    this.setState({
      checkedList: e.target.checked ? plainOptions : [],
      indeterminate: false,
      checkAll: e.target.checked
  render() {
    console.log(this.state.checkedList)
    return (
        <div style={{ borderBottom: "1px solid #E9E9E9" }}>
          <Checkbox
            indeterminate={this.state.indeterminate}
            onChange={this.onCheckAllChange}
            checked={this.state.checkAll}
            Check all
          </Checkbox>
        <br />
        <CheckboxGroup
          options={plainOptions}
          value={this.state.checkedList}
          onChange={this.onChange}

使用hooks绑定多关联组件

  // 选择数据批次 ALL勾选change
  const onDcCheckboxChange = (e: CheckboxChangeEvent) => {
    setIndeterminate(false)//空或者全选
    setBoxChecked(e.target.checked)
    let finResult = boxChecked ? [] : newarray
    setNameArray(finResult)
  // 单独选择后的勾选
  const inDcCheckboxChange = e => {
    //当前的e为复选框后面的值为checkedvalue
    //通过this.state.nameArray保存当前选项的选中状态,并将inDccheckboxchange与onDcCheckboxChange关联了起来
    setNameArray(e)
    setIndeterminate(!!e.length&&e.length<=newarray.length)//true输出&&后面的,false直接输出false
    setBoxChecked(e.length==newarray.length)

使用onDcCheckboxChange控制全选按钮,checkbox的onchange方法中传递为Function(e:Event),checkboxgroup的onchange方法中传递的为checkedValue(选中的值,格式为Array)

  // 使用checked与indeterminate协同控制checkbox的显示,checkbox在绑定了全选的情况下有三种展示形态,是难点请记住