HOOK

react HOOK 是react16.8新增的一个特性 主要作用 就是让无状态组件/函数组件 可以使用状态 ref等一些特性

HOOK 不能在 class组件中使用

类组件与函数组件的区别

无状态组件 的创建比类组件的可读性更好 就是大大减少了组件编写代码量 在组件内容只有一个jsx编写效率更高

函数组件中不用this 因为函数组件没有实例化的过程

useState

useState 是reactHOOK给我们提供的 最基本最常用的一个HOOK 主要作用就是用来管理当前本地的状态

useState() 返回值是一个数组(长度为2)数组的第一项标识的是当前的值 数组的第二项标识的时候修改这个值的函数

let [xiaoming , setXiaoming]=useState(初始值)

创建与读取

1
2
3
4
5
6
7
8
9
10
11
12
import {useState} from "react"
let Funcom=()=>{
// 使用useState()c创建函数组件的状态
let [xiaoming,setxiaoming]=useState("你好么么哒!!!")
return (
<div>
{/* 读取 */}
<h1>我是一个函数组件--{xiaoming}</h1>
</div>
)
}
export default Funcom

修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import {useState} from "react"
let Funcom=()=>{
// 使用useState()创建函数组件的状态
let [xiaoming,setxiaoming]=useState("你好么么哒!!!")
return (
<div>
{/* 读取 */}
<h1>我是一个函数组件--{xiaoming}</h1>
{/* 修改数据 */}
<button onClick={()=>{setxiaoming(xiaoming="你好呵呵哒")}}>点我修改</button>
</div>
)
}
export default Funcom

创建多个状态呢

1.你写多个useState

1
2
3
4
5
6
7
8
9
10
11
12
13
import {useState} from "react"
let Funcom=()=>{
// 1.你写多个useState了解
let [xiaoming,setxiaoming]=useState("1")
let [xiaohong,setxiaohong]=useState("2")

return (
<div>
{xiaoming}---{xiaohong}
</div>
)
}
export default Funcom

2.一次行创建多个值

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 {useState} from "react"
let Funcom=()=>{
// 1.你写多个useState了解
// let [xiaoming,setxiaoming]=useState("1")
// let [xiaohong,setxiaohong]=useState("2")

// 2.一次性创建多个值
let [xiaoming,setxiaoming]=useState({
dataa:"第一个值1",
datab:"第一个值2",
datac:"第一个值3",
datad:"第一个值4",
datae:"第一个值5",
dataf:"第一个值6"
})
return (
<div>
{/* {xiaoming}---{xiaohong} */}

{xiaoming.dataa}----{xiaoming.datad}
</div>
)
}
export default Funcom

一次性创建多个值怎么修改

1.多个useState 要修改的话就依次调用其中的修改方法

2.一次行创建多个值的方式如何修改呢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import {useState} from "react"
let Funcom=()=>{
// 1.你写多个useState了解
// let [xiaoming,setxiaoming]=useState("1")
// let [xiaohong,setxiaohong]=useState("2")

// 2.一次性创建多个值
let [xiaoming,setxiaoming]=useState({
dataa:"第一个值1",
datab:"第一个值2",
datac:"第一个值3",
datad:"第一个值4",
datae:"第一个值5",
dataf:"第一个值6"
})

let fun=()=>{
// 一次性创建多个的修改操作 不要忘了保留原始数据
setxiaoming({...xiaoming,datad:"我被改了"})
}

return (
<div>
{/* {xiaoming}---{xiaohong} */}

{xiaoming.dataa}----{xiaoming.datad}
<button onClick={fun}>点我修改</button>
</div>
)
}
export default Funcom

useRef

就是可以让函数组件使用ref的一个技术

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import {useRef} from "react"
let Funcom=()=>{
// 1.创建出useRef
let xiaoming=useRef(null)

let fun=()=>{
// 3.获取
console.log(xiaoming.current.value);
}
return (
<div>
{/* 2.绑定使用 */}
<input type="text" ref={xiaoming}/>
<button onClick={fun}>点我得到输入框的值</button>
</div>
)
}
export default Funcom

useEffect

Function Component 不存在生命周期,所以不要把 Class Component 的生命周期概念搬过来试图对号入座。

useEffect就可以让函数组件使用生命周期

语法:

1
useEffect(第一个参数是一个函数,第二个参数是一个数组)

就是如下三个钩子函数的综合体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 渲染完毕
componentDidMount() {

}

// 修改完毕
componentDidUpdate() {

}

// 准备销毁
componentWillUnmount() {

}

模拟componentDidMount

useEffect(()=>{console.log(‘第一次渲染时调用’)},[])

第二个参数为一个空数组,可以模拟componentDidMount

因为函数组件每次更新的时候就是组件会被全部调用一次 传递了空数组就相当于欺骗了react我要监听某个内容 所以只是第一次调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import {useEffect} from "react"
let Funcom=()=>{
useEffect(()=>{
document.title="么么哒"
console.log("我自动执行了");
},[])
return (
<div>
<h1>函数组件可以使用生命周期</h1>
</div>
)
}
export default Funcom

模拟componentDidUpdate

没有第二个参数代表监听所有的属性更新但是注意首次也会触发

因为函数组件每次更新的时候就是组件会被全部调用一次 什么都不传那么每次修改就会触发

1
useEffect(()=>{console.log('任意属性该改变')}) 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import React, { useState, useEffect } from 'react'

export default function Demo() {
let [xiaoming, setXiaoming] = useState("666")
useEffect(() => {
console.log("谁修改我都会触发")
})
let fun = () => {
setXiaoming("我变了")
}
return (
<>
<div>demo--{xiaoming}</div>
<button onClick={fun}>点我修改</button>
</>
)
}

监听多个属性的变化需要将属性作为数组传入第二个参数。

因为函数组件每次更新的时候就是组件会被全部调用一次 传递了值就会告诉react我要监听某个内容 所以只有这些值改变的时候就会被调用

1
useEffect(()=>{console.log('n变了')},[n,m]) 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, { useState, useEffect } from 'react'

export default function Demo() {
let [xiaoming, setXiaoming] = useState("666")
let [xiaohong, setXiaohong] = useState("777")
// 因为监听了xiaohong 所以修改小明的时候不会触发
useEffect(() => {
console.log("谁修改我都会触发")
},[xiaohong])
let fun = () => {
setXiaoming("我变了")
}
return (
<>
<div>demo--{xiaoming}--{xiaohong}</div>
<button onClick={fun}>点我修改</button>
</>
)
}

模拟componentWillUnmount

通常,组件卸载时需要清除 effect 创建的诸如订阅或计时器 ID 等资源

useEffect函数返回的函数可以表示组件死亡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React,{useState,useEffect} from 'react'

function Zi() {
useEffect(()=>{
// 调用子组件的时候执行一个定时函数
let time= setInterval(()=>{
console.log("你好")
},1000)
// 在effect中return 一个函数就是在销毁的时候执行
return ()=>{
console.log("我被销毁了")
clearInterval(time)
}
})
return (
<div>我是Zi组件</div>
)
}

export default function Demo() {
let [bool,setbool]=useState(true)
return (
<div>
我是父组件
<button onClick={()=>{setbool(!bool)}}>点我显示和隐藏子组件</button>
{bool&& <Zi></Zi>}


</div>
)
}

useContext

接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。

可以直接获取到context对象的Consumer消费者中的数据

在没有使用的时候跨组件传值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import React, { createContext } from 'react'
let context = createContext()
function Sun() {
return (
<div>

<context.Consumer>
{
(value)=>{
return (
<h1>{value.name}</h1>
)
}
}
</context.Consumer>
</div>
)
}

function Zi() {
return (
<div>

<Sun></Sun>
</div>
)
}

export default function Fu() {
return (
<context.Provider value={{name:"xiaoyang",age:18}}>
<div>

<Zi></Zi>
</div>
</context.Provider>
)
}

使用useContext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import React, { createContext,useContext } from 'react'
let context = createContext()
function Sun() {
// 使用useContext可以直接得到Consumer中的数据
let value=useContext(context)
return (
<div>

<h1>{value.name}</h1>
</div>
)
}

function Zi() {
return (
<div>

<Sun></Sun>
</div>
)
}

export default function Fu() {
return (
<context.Provider value={{name:"xiaoyang",age:18}}>
<div>

<Zi></Zi>
</div>
</context.Provider>
)
}

useReducer

就是在react中 函数组件如果对一个state有多次修改 那么可以使用useReducer来对其内容进行简化

语法:

let [保存这个值得变量,是对这个变量修改的一个方法]=useReducer(修改数据的reducer方法,”初始化值”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import {useReducer} from "react"
let Funcom=()=>{
// 因为useReducer是对一个数据需要有多次修改的时候使用的
// state就是当前的这个状态
// dispat触发修改操作

let [state,dispatch]=useReducer(reducer,18)
function reducer(state,action){
switch (action.type) {
case "ADD":
return state+1
break;
case "DEL":
return state-1
break;

default:
return state
break;
}
}
var add=()=>{
dispatch({type:"ADD"})
}
var del=()=>{
dispatch({type:"DEL"})
}

return (
<div>

<h1>useReducer--{state}</h1>
<button onClick={add}>+1</button>
<button onClick={del}>-1</button>
</div>
)
}

export default Funcom

或者
import {useReducer} from "react"
let Funcom=()=>{
// 因为useReducer是对一个数据需要有多次修改的时候使用的
// state就是当前的这个状态
// dispat触发修改操作
var reducer=(state,action)=>{
switch (action.type) {
case "ADD":
return state+1
break;
case "DEL":
return state-1
break;

default:
return state
break;
}
}
let [state,dispatch]=useReducer(reducer,18)

var add=()=>{
dispatch({type:"ADD"})
}
var del=()=>{
dispatch({type:"DEL"})
}

return (
<div>

<h1>useReducer--{state}</h1>
<button onClick={add}>+1</button>
<button onClick={del}>-1</button>
</div>
)
}

export default Funcom