目录
一、React Hooks的使用
1、React的组件
React的组件创建方式,一种是类组件,一种是纯函数组件
(1)类组件:class 类名 extends React.Component{}
(2)函数组件:function 函数名([参数]){}
2、函数组件和类组件的区别
(1)函数组件没有状态(state),类组件有
(2)函数组件没有生命周期,类组件有(挂载、更新、销毁)
(3)函数组件没有this,类组件有
注意:函数组件更适合做UI展示,类组件更适合做复杂的业务逻辑组件
3、React Hooks出现的原因
类组件功能齐全但代码很重,函数组件很轻量但是没有状态、this等功能。为了解决这个问题(代码轻量、还要有状态管理),React团队就推出了React Hooks(加强版的函数组件--实现状态管理)
4、React Hooks的基本思想
组件尽量写成纯函数的(函数组件),若需要外部功能或特殊的需求,使用"钩子"将外部功能钩进来即可
5、React Hooks的钩子函数
React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。而React Hooks 就是我们所说的“钩子”。
(1)四种常用的钩子函数
不同的钩子为函数引入不同的外部功能,React Hooks约定,钩子一律使用use前缀命名。所以,自己定义的钩子都要命名为useXXX。
① useState():状态钩子
- useState():状态钩子。纯函数组件没有状态,useState()用于为函数组件引入状态
- 该函数的返回值为具有2个单元的一维数组,数组的第一个单元存放的是状态属性,
- 第二个单元存放的是修改状态属性值的函数,函数名以set后面跟属性名(采用小驼峰命名法)
import React,{ useState } from "react";
const NewCount = ()=> {
const [ count,setCount ] = useState(0)
const addCount= ()=> {
let newCount = count;
setCount(newCount +=1)
}
return (
<>
<p> { count }</p>
<button onClick={ addCount }>Count++</button>
</>
)
}
export default NewCount;
count相当于一个状态属性,setCount相当于内组件里面的this.setState,useState(0),将0赋给count,useState里面的参数就是状态属性里面的初始值
在useState()中,它接受状态的初始值作为参数,例如上例中计数的初始值(0),它返回一个数组,其中数组第一项为一个变量,指向状态的当前值,类似this.state;第二项是一个函数,用来更新状态,类似setState。函数的命名,约定为set前缀加状态的变量名。
② useContext()
- useContext():共享状态钩子。作用就是可以做状态的分发,在React16.X以后支持,避免了react逐层通过Props传递数据。
- 第一步:创建全局的Context,const AppContext = React.createContext([初始化参数])
- 第二步:通过全局的Context进行状态值的共享
<AppContext.Provider value={{属性名:值}}> <组件1 /> <组件2 /> </AppContext>
import React, { useContext } from "react";
const HookTest = ()=> {
const AppContext = React.createContext({}); //创建AppContext的常量
const A = ()=> { //A组件
const { name } = useContext(AppContext) //用userContext将AppContext赋给name,相当于解构,将AppContext中的name属性解构出来
return (
<p>
我是A组件,我的名字是:{ name };
<span>我是A的子标签:{ name }</span>
</p>
)
}
const B= ()=> { //B组件
const { name } = useContext(AppContext);
return (
<p>我是B组件,名字是: { name }</p>
)
}
return (
<AppContext.Provider value={{ name: '小森'}}>
<A />
<B />
</AppContext.Provider>
)
}
export default HookTest;
③ useReducer():Action钩子
const [state, dispatch] = useReducer(reducer, initialState)
它接受reducer函数和状态的初始值作为参数,返回一个数组,其中第一项为当前的状态值,第二项为发送action的dispatch函数
④ useEffect():副作用钩子
可以用来更好的处理副作用,如异步请求等,Hooks的useEffect()也是为函数组件提供了处理副作用的钩子。在类组件中我们会把请求放在componentDidMount里面,在函数组件中我们可以使用useEffect()。
useEffect(() => {},[array])
useEffect()接受两个参数,第一个参数是要进行的异步操作,第二个参数是一个数组,用来给出Effect的依赖项,只要这个数组发生变化,useEffect()就会执行。当第二项省略不填时,useEffect()会在每次组件渲染时执行。这一点类似于类组件的componentDidMount
//通过useEffect()模拟一个异步加载数据。
import React,{ useState,useEffect } from "react";
const AsyncPage = () => {
const [loading,setLoading] = useState(true)
useEffect(()=> {
setTimeout(()=> {
setLoading(false)
},5000)
})//第二个参数为默认的话,组件每一次刷新,都会向后台发起一次请求
return (
loading? <p>loading...</p>: <p>异步请求完成</p>
)
}
export default AsyncPage;
//useEffect()依赖第二项数组变化
import React,{ useState,useEffect } from "react";
const AsyncPage = ({name}) => {
const [loading, setLoading] = useState(true)
const [person, setPerson] = useState({})
useEffect(() => {
setLoading(true)
setTimeout(()=> {
setLoading(false)
setPerson({name})
},2000)
},[name])
return (
<>
{loading?<p>Loading...</p>:<p>{person.name}</p>}
</>
)
}
const PersonPage = ()=> {
const [state,setState] = useState('')
const changeName = (name)=> {
setState(name);
}
return (
<>
<AsyncPage name={ state }/>
<button onClick={()=>{ changeName('小森')}}>小森</button>
<button onClick={()=>{ changeName('小沈')}}>小沈</button>
</>
)
}
export default PersonPage;