1.概述
React官方网站原文:Hooks 是一项新功能提案,可让您在不编写类的情况下使用 state(状态) 和其他 React 功能。
我总结了下使用Hooks的理由:
1.解决class中的代码层级复杂。
2.类的生命周期复杂。
3.无状态组件,因工作需求要求改成有状态组件,改成class组件成本比较高。
2.useState(保存组件状态)
补充说明useState还是记忆组件,只在创建该组件的时候初始化一次,这样可保证每次修改的值可以保存起来。示例代码做一个简单的修改名称,逻辑也比较简单直接上代码:
import React, { useState } from 'react'
export default function App() {
const [name,setName]=useState('张三')
return (
<div>App-{name}
<button onClick={()=>{
setName('李四') //把name张三修改成了李四
console.log(name);
}}>修改</button>
</div>
)
}
3.useEffect(处理副作用)
先来了解下什么是副作用,副作用是指函数或者表达式的行为依赖于外部世界。
语法: useEffect(()=>{},[]) ;两个参数:参数一会点函数把要处理的逻辑放在里面,比如网络请求或者逻辑处理。参数二数组:依赖的状态;空数组,表示不依赖,如果传入空数组则表示只会执行一次,如果传入依赖状态则依赖状态的只改变函数就会执行一遍。
补充说明:useEffect 是会在整个页面渲染完才会调用的,类似于类组件的生命周期,但不完全相同。示例代码做了个简单的网络请求:
import React, { useEffect, useState } from 'react'
import axios from 'axios'
export default function App() {
const [list, setList] = useState([])
useEffect(() => {
axios({
method: 'get',
url: 'move.json'
}).then(res => {
console.log(res.data.data);
setList(res.data.data.films)
})
},
[])//传空数组,表示不依赖任何东西
return (
<div>
<ul>
{list.map(item => <li key={item.filmId}>{item.name}</li>)}
</ul>
</div>
)
}
useEffect的清除方法,比如说你在useEffect回调方法里面中设置里定时器,当组件消失的时候应该销毁掉。上代码
import React, { useEffect, useState } from 'react'
export default function App() {
const [show, setShow] = useState(true)
return (
<div>
<button onClick={() => {
setShow(false)
}}>销毁</button>
{show ? <Child></Child> : ""}
</div>
)
}
function Child() {
let timer = null
const [name, setName] = useState('张三')
useEffect(() => {
console.log(name);
timer = setInterval(() => {
console.log('定时器');
}, 1000)
//销毁是执行一次,依赖更新一次也会执行一次。
return () => {
clearInterval(timer)
timer = null
console.log('xiaohui');
}
}, [name])
return (
<div><button onClick={() => {
setName('李四')
}}>Child</button></div>
)
}
4.useCallback(记忆函数)
useCallback(()=>{},[]) ;该方法返回的是一个函数方法,参数一:回调函数,参数二:依赖的状态;空数组,表示不依赖,如果传入空数组则表示只会执行一次,如果传入依赖状态则依赖状态的只改变函数就会执行一遍返回更新后的函数。
import React, { useCallback, useState } from 'react'
export default function App() {
const [name,setName]=useState('张三')
let sum=0;
console.log(sum);
const handleAdd=useCallback(()=>{
console.log(sum++);
setName('lisi'+sum)
},[])
//只有name改变后, 这个函数才会重新声明一次,
//如果传入空数组, 那么就是第一次创建后就被缓存, 如果name后期改变了,拿到的还是老的name。
//如果不传第二个参数,每次都会重新声明一次,拿到的就是最新的name
return (
<div>
app-{name}
<button onClick={ handleAdd}>anniu </button></div>
)
}
5.useMemo
useMemo和useCallback用法很类似,useCallback 不会执行第一个参数函数,而是将它返回给你,而 useMemo 会执行第一个函数并且将函数执行结果返回给你。
直接上代码
import React, { useMemo, useState } from 'react'
export default function App() {
const [name, setName] = useState('xiaoming')
const handleName = useMemo(() => name.toLocaleUpperCase(), [name])
return (
<div>App-{handleName}
<button onClick={()=>{
setName('lisi')
}}>gaibian</button>
</div>
)
}
6.useRef
useRef 绑定dom或者组件,也可以保存值,useRef也具有记忆功能。
直接上代码
import React, { useRef } from 'react'
export default function App() {
//绑定dom或者组件
const ref = useRef()
//useref保存值
const myCount=useRef(0)
return (
<div>
<input ref={ref}></input>
<button onClick={() => {
console.log(ref.current.value);
ref.current.value = '';
myCount.current++;
console.log(myCount.current);
}}>按钮</button>
</div>
)
}
7.useContext
父组件给子组件传值。比较简单直接上代码。
import React, { useContext } from 'react'
const Context =React.createContext()
export default function App() {
return (
<Context.Provider
value={
{name:'lisi'}}>
<div>
<Ietm></Ietm>
</div>
</Context.Provider>
)
}
function Ietm(){
const value=useContext(Context)
return (
<div>ietm-{value.name}</div>
)
}
8.useReducer
语法:const [state, dispatch] = useReducer(reducer, initialState);
useState的替代方案。接受类型为 (state, action) => newState
的reducer,并返回与 dispatch
方法配对的当前状态。 (如果你熟悉Redux,你已经知道它是如何工作的。),主要把修改状态的方法抽取出来。
useReducer一步都是结合着useContext使用,可以减少代码层级。直接上代码
import React, { useContext, useReducer } from 'react'
//preState 老状态 action改变的类型
function reducer(preState, action) {
let newSate = { ...preState };
switch (action.type) {
case "add":
newSate.count++
return newSate;
case "sub":
newSate.count--
return newSate;
}
return preState;
}
const initialState = {
count: 0
}
const Context = React.createContext()
export default function App() {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<Context.Provider value={
{ state, dispatch }}>
<div>
<Child></Child>
</div>
</Context.Provider>
)
}
function Child() {
const { state, dispatch } = useContext(Context)
return (
<div>
计数器:{state.count}
<div>
<button
onClick={() => {
dispatch({ type: "add" })
}}
>+</button>
<button
onClick={() => {
dispatch({ type: "sub" })
}}
>-</button>
</div>
</div>
)
}
9.构建你自己的 Hooks
import React, { useEffect, useState } from 'react'
function useToLocaleUpperCase(text) {
const [name, setName] = useState(text)
useEffect(() => {
setName(name.toLocaleUpperCase())
}, [])
return { name };
}
export default function App() {
const { name } = useToLocaleUpperCase('zhansan')
return (
<div>App-{name}
<Child></Child>
</div>
)
}
function Child() {
const { name } = useToLocaleUpperCase('lisi')
return (
<div>App-{name}</div>
)
}