hook学习01
- Hooks理解
- useState
- useEffect
- 自定义hook函数
Hooks理解
react组件分为类组件和函数组件
函数组件是一个更加匹配react的设计理念UI = f(data),利于逻辑拆分与重用的组件表达形式,而之前的函数组件是不可以有自己的状态的,为了能让函数组件可以拥有自己的状态,react16.8开始,Hooks出现
- Hooks出现后,类组件并没有移除,还是可以使用
- Hooks出现有,不能把函数成为无状态组件
- Hooks只能在函数组件中使用
Hooks出现解决的问题:
1,组件的状态逻辑复用
2,claas组件自身的问题
- 告别难以理解的Class
- 解决业务逻辑难以拆分的问题
- 使状态逻辑复用变得简单可行
- 函数组件在设计思想上,更加契合react理念
useState
提供一个状态,以及修改状态的方法,useState后的值表示初始化的值
// useState
// 1,导入useState函数 react
// 2,执行这个函数并且传入初始值,必须在函数组件中
// 3,[数据,修改数据的方法]
// 4,使用数据,修改数据
import { useState } from 'react'
function App () {// useState返回一个数组,如下是结构赋值的写法// 名字是可以自定义的 -> 保持语义化// 顺序不可以换,数组是有序的,第一个参数是数据状态,第二个参数就是修改数据的方法// setCount是一个函数,作用: 用于修改count状态的值,依旧保持不能直接修改原值,还是用于计算得到的新值替换原值// count和setCount是绑在一起的const [count, setCount] = useState(0)return (<div><button onClick={() => setCount(count + 1)}>{count}</button></div>)
}
更新过程:
// 当调用setCount时,更新过程// 首次渲染
/*** 首次被渲染时,组件内部的代码会被执行一次* 其中useState也会跟着执行* useState(0)初始值,只在首次渲染时生效*/// 更新渲染
/*** setCount都会更新* APP组件会再次渲染,这个函数会再次执行* useState再次执行得到的新的count执行不是0,而是修改后的1,模板会使用新值*/
useState调用多次,初始化多个状态
function App () {const [count, setCount] = useState(0)const [flag, setFlag] = useState(true)const [list, setList] = useState([1, 2, 3])console.log(count)return (<div><button onClick={() => setCount(count + 1)}>{count}</button>{list.map(item => <h2 key={item}>{item}</h2>)}</div>)
}
注意事项:
-
只能出现在函数组件中
-
不能嵌套在if/for/其他函数中(react按照hooks的调用顺序识别每一个hook),如下是错误写法
let name = 'seek' function Show(){name = 'seek18'// 错误写法if (name = 'seek18'){const [age,setAge] = useState(18)}const [flag,setFlag] = useState(true) }
可以通过开发者工具查看hook状态
useEffect
函数的副作用:
一个函数除了主作用,其他的作用就是副作用,对于react组件来说,主作用就是根据数据渲染UI,除此以外都是副作用(例如:手动修改DOM)
常见的副作用:
- ajax请求
- 手动修改dom
- localstorage操作
useEffect函数的作用就是为react函数组件提供副作用处理
import { useEffect, useState } from 'react'// 在修改数据后,把count值放到页面标题中
// 1,导入useEffect函数
// 2,在函数组件中执行
// 3,当我们通过修改状态更新组件时,副作用也不断执行
function App () {const [count, setCount] = useState(0)useEffect(() => {document.title = count})return (<div><button onClick={() => setCount(count + 1)}>{count}</button></div>)
}export default App
通过依赖项,控制执行实际
1,默认状态
2,添加一个空数组
3,依赖特性项
function App () {const [count, setCount] = useState(0)const [name, setName] = useState('seek')// 默认:组件第一次渲染以及每次更新执行useEffect(() => {document.title = countconsole.log('每次执行')})// 只会在首次渲染执行useEffect(() => {console.log('first console')}, [])// 添加特定的依赖项,表示只有修改count才会执行,后面是一个数组useEffect(() => {console.log('count console')}, [count])// 同时修改count和name,或者只改一个都会执行useEffect(() => {console.log('count console')}, [count,name])return (<div><button onClick={() => setCount(count + 1)}>{count}</button><button onClick={() => setName(name + 'a')}>{name}</button></div>)
}
注意事项:
useEffect 回调函数中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中,如果不添加依赖项就会有bug出现
hook的出现,就是不想用生命周期概念,也可以写业务代码
自定义hook函数
自定义一个hook函数,实现获取滚动距离Y,const [y] = useWindowScroll()
import { useEffect, useState } from 'react'function useWindowScroll () {const [y, setY] = useState(0)window.addEventListener('scroll', () => {const h = document.documentElement.scrollTopsetY(h)})return [y]
}function App () {const [y] = useWindowScroll()return (<div style={{ height: '12000px' }}>{y}</div>)
}export default App
自定义hook函数,可以自动同步到本地LocalStorage
const [message, setMessage] = useLocalStorage(key,defaultValue)
function useLocalStorage (key, defaultValue) {const [message, setMessage] = useState(defaultValue)useEffect(() => {window.localStorage.setItem(key, message)}, [key, message])return [message, setMessage]
}