1. 前言
what Hook
Hook
是React 16.8
的新增特性。它可以让你在不编写class组件
的情况下使用state
以及其他的React
特性。
2. why
之前的组件形式缺点
- 函数组件一般是无状态组件
- 类组件可以有状态,也可以无状态
- 组件之间
复用
状态逻辑很难
,组件维护
越来越复杂
class组件
中的this
难以理解
3. Hook 基本概念
现在的函数组件也可以是有状态的组件,内部也可以维护自身的状态以及做一些逻辑方面的处理
- 避免地狱式嵌套,可读性提高
- 函数式组件,比
class组件
更容易理解- UI和逻辑更容易分离
- 基本不需要
this
4. 引入hook之前的代码问题
简单的计数器案例
function MyCom(){ let count = 0 function add(){ count ++ console.log(count) } return ( <div> {count} <button onClick={add}>点我</button> </div> ) } ReactDOM.render( <MyCom/>, document.getElementById("app") )
点击按钮界面变量不跟着变
5. Hooks 有哪些常用的API
Hooks
让我们的函数组件拥有了类组件的特性,例如组件内的状态、生命周期1.useState 组件内的状态
2.useEffect 生命周期
3.其他
6. 语法-State
const [state,setState] = useState(initialState)
1.
state
为变量2.
initialState state
变量的初始值
3.
setState
修改state
值的方法4.
setState
异步执行
7.hook -useState
包含--基本类型写法
包含--引用类型写法
function MyCom(){ // 声明一个叫 count 的state变量, 初始值为0 let [count, setCount] = React.useState(0) // 声明一个 叫obj的 state变量 初始值为空对象 let [obj, setObj] = React.useState({}) function add(){ // 基本类型的修改 setCount(++count) // 引用类型的修改 setObj({ name: 'a'+count }) console.log(count) } return ( <div> {count}-{obj.name} <button onClick={add}>点我</button> </div> ) }
在函数组件中通过
useState
实现函数内部维护state
,参数为state
默认的值,返回值是一个数组,第一个值为当前的
state
,第二个值为更新
state
的函数
8 类组件 VS 函数式组件
1.
state
声明方式:在函数组件中通过
useState
直接获取,类组件通过constructor
构造函数中设置2.
state
读取方式:在函数组件中
直接使用变量
,类组件通过this.state.count
的方式获取3.
state
更新方式:在函数组件中通过
setCount
更新,类组件通过this.setState()
总结就是
useState
使用起来更为简洁
,减少了this
指向不明确的情况
9. hook-钩子 -useEffect
9.1语法
React.useEffect
(参数1,参数2)参数1 是回调函数
参数2 是参数1 这个函数监听的变量
9.2 useEffect 相当于3个钩子的综合
1.componentDidMount
2.componentDidUpdate
3.componentWillUnMount
9.3 分析
参数2 为空 不写: DidMount+DidUpdate
在第一次渲染和更新之后都会执行
参数2 空数组[] ,DidMount
第一次渲染后
参数2 [变量], 监听变量的改变 componentDidUpdate
React
将对前一次渲染的变量值count
和后一次渲染的count
值进行比较
9.4 代码
function MyCom(){ let [count, setCount] = React.useState(0) let [obj, setObj] = React.useState({}) function add(){ // setCount(++count) setObj({ name: 'a'+count }) console.log(count) } React.useEffect(() => { console.log("初始化或更新1") }) React.useEffect(() => { console.log("初始化2") }, []) React.useEffect(() => { console.log("初始化或count更新3") }, [count,obj]) return ( <div> {count}-{obj.name} <button onClick={add}>点我</button> </div> ) }
这个建议 还是自己写写,因为代码本身也很简单
10. 清除函数
回调函数中可以返回一个清除函数,这是
effect
可选的清除机制,相当于类组件中componentwillUnmount
生命周期函数,可做一些清除副作用的操作,比如定时器
// 创建响应数据以及修改方法 let [num,setNum]=useState(20); // 会在更新之前 执行指定的销毁函数 // 防止初始化的代码 重复绑定 定时器 useEffect(()=>{ console.log("useEffect") // 绑定定时器 让num递增 let timer=setInterval(()=>{ console.log("定时器"); num++; setNum(num);//num发生变化 },1000); return ()=>{//销毁 clearInterval(timer); } })
11. 总结
1.每调用
useHook
一次都会生成一份独立的状态2.通过自定义
hook
能够更好的封装我们的功能3.
useEffect
相当于componentDidMount,componentDidUpdate 和 componentWillUnmount
这三个生命周期函数的组合
12.其他hooks
useReducer
useCallback
useMemo
useRef
13. 这里再梳理个 useReducer
其实就是 useState的替代版 主要用来 结合
redux
中的reducer
13.1 简单的看下 store 中 redux的结构
import { createStore } from "redux"; let defaultState = { counter:0 } export const reducer = (state=defaultState,{type,payload=10})=>{ switch (type){ case "counter/incremented":{ let tempState = JSON.parse(JSON.stringify(state)); tempState.counter += payload return tempState } case "counter/decremented":{ return{ ...state, counter:state.counter - payload } } default:{ console.log("switch 默认") return state } } } let store = createStore(reducer) export default store
13.2 使用 useReducer
import { useState, useEffect ,useReducer} from 'react'; import {reducer} from "../store" function HookPage() { const [state, dispatch] = useReducer(reducer, {counter:99}) } return ( <div className="App"> <h1>{state.counter}</h1> <button onClick={()=>{ dispatch({type:"counter/decremented",payload:100}) }}> redux</button> </div> ); } export default HookPage;
13.3 分析
useReducer()
参数1: 就是reducer
参数2:就是初始值
参数3:是个初始化的回调函数
14. 完整的 组件内使用 hook
import { useState, useEffect ,useReducer} from 'react'; import {reducer} from "../store" function HookPage() { let [counter, setCounter] = useState(0) let [person, setPerson] = useState({ name: "yzs" }) const [state, dispatch] = useReducer(reducer, {counter:99}) function increase(v) { counter += v setCounter(counter) } function update() { setPerson({ name: "郑州" }) } // **************钩子 useEffect(() => { console.log("初始化或者更新") }) useEffect(() => { console.log("[] 初始化") },[]) useEffect(() => { console.log("初始化或 对应的值变化") },[counter,person]) return ( <div className="App"> <h1>{counter}</h1> <button onClick={() => { increase(10) }}>增加</button> <hr /> <h1>{person.name}</h1> <button onClick={update}> name</button> <hr/> <h1>{state.counter}</h1> <button onClick={()=>{ dispatch({type:"counter/decremented",payload:100}) }}> redux</button> </div> ); } export default HookPage;
15. 总结性hook
可参考这篇文章 react常用-hook总结