前言

虽然react一般都是class类的方式编写,但有时为了简单,就使用函数编写,但在以前这是无副作用的函数,所以很多事都无法去做,比如后期为了维护而不得不在函数里使用state等时,这就不会符合无副作用的函数了,所以react会报错,而这是使用hooks就可以拯救啦,当然也有喜欢使用函数式编写的人来说也是福音,因为hooks基本上支持所有react生命周期,state,redux等等,与编写class方式差不多等效了。

State

引入react里的useState。
useState的参数就像state初始化值。
useState返回的值一个数组,数组中第一个参数是以前的state,第二个参数是setState,由于是参数,所以可以自己命名,不用想以前就state,setState这样。

例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { Component, useState, useEffect } from 'react';
import { InputItem, List } from 'antd-mobile';

export const getText = function(props){
const [test, setTest] = useState('');
function onChange(val){
setTest(val);
}

return (
<div>
<List>
<InputItem value={test} onChange={onChange}>hooks测试</InputItem>
</List>
<List>
<div>{test}</div>
</List>
</div>
);
}

Effect

引入react里的Effect。
useEffect增加了从功能组件执行副作用的功能,其实这个钩子就是让函数支持react生命周期。
它的目的是作为componentDidMount,componentDidUpdate以及componentWillUnmount,只是都在这个useEffect钩子实现。

  1. useEffect的第二参数为空数组[],效果如componentDidMount:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import React, { Component, useState, useEffect } from 'react';
    import { InputItem, List } from 'antd-mobile';


    export const getText = function(props){

    // 调用父级组件函数更新state
    useEffect(()=>{
    props.setVal(Math.floor(Math.random()*100));
    },[]);

    return (
    <div>
    <List>
    <div>{props.value}</div>
    </List>
    </div>
    );
    }
  2. useEffect的第二参数不传,效果如componentDidUpdate,但初始加载也会触发:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import React, { Component, useState, useEffect } from 'react';
    import { InputItem, List } from 'antd-mobile';


    export const getText = function(props){

    // 调用父级组件函数更新state
    useEffect(()=>{
    props.setVal(Math.floor(Math.random()*100));
    });

    return (
    <div>
    <List>
    <div>{props.value}</div>
    </List>
    </div>
    );
    }
  3. useEffect里函数的返回值,效果如componentWillUnmount,在组件卸载调用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import React, { Component, useState, useEffect } from 'react';
    import { InputItem, List } from 'antd-mobile';


    export const getText = function(props){
    const timer = setInterval(()=>{
    console.log(+new Date());
    });
    // 调用父级组件函数更新state
    useEffect(()=>{
    props.setVal(Math.floor(Math.random()*100));
    return ()=>{
    clearInterVal(timer);
    }
    });

    return (
    <div>
    <List>
    <div>{props.value}</div>
    </List>
    </div>
    );
    }
  4. useEffect的第二参数数组有对应的state或props值,只要当前值更新了才触发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { Component, useState, useEffect } from 'react';
import { InputItem, List } from 'antd-mobile';


export const getText = function(props){

// 调用父级组件函数更新state
useEffect(()=>{
props.setVal(Math.floor(Math.random()*100));
},[props.value]);

return (
<div>
<List>
<div>{props.value}</div>
</List>
</div>
);
}

自定义钩子

就是抽取相同逻辑的部分封装成一个新的钩子,而钩子使用hooks的钩子封装实现,然后返回一个目标内容,如值。

自定义钩子:

1
2
3
4
5
6
7
8
9
10
import React, { Component, useState, useEffect } from 'react';
export const getHook = function(vId,props){
const [ssId, setSsId] = useState('');
useEffect(()=>{
props.setVal(Math.floor(Math.random()*100));
setSsId(vId);
},[props.value]);

return ssId;
}

使用自定义钩子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component, useState, useEffect } from 'react';
import { InputItem, List } from 'antd-mobile';
improt {getHook} from './hooks';

export const getText = function(props){
const nVal = getHook("xx",props);

return (
<div>
<List>
<div>{props.value}</div>
</List>
</div>
);
}

使用规则

  1. 只能在顶层调用Hooks。不要在循环,条件或嵌套函数中调用Hook。
  2. 只能在functional component中使用,所以如果在class使用一定要是组件的形式,而不是函数调用的方式,不是会当成一个在class里使用hooks。

参考

react官网有很详细的资料,而且以上的只是当用的,Hooks还提供了别的钩子。
react官方Hooks