1.什么是Hook?
- Hook 是 React 16.8 的新增特性,
它可以让函数式组件拥有类组件特性
2. 使用hooks 理由:
- 高阶组件为了复用,导致代码层级复杂
- 生命周期的复杂
- 写成 function函数组件 ,无状态组件, 因为需要状态,又改成了class,成本高 ```
- 在Hook出现之前, 如果我们想在组件中保存自己的状态,
如果我们想在组件的某个生命周期中做一些事情, 那么我们必须使用类组件
- 但是类组件的学习成本是比较高的, 你必须懂得ES6的class, 你必须懂得箭头函数
- 但是在类组件的同一个生命周期方法中, 我们可能会编写很多不同的业务逻辑代码 这样就导致了大量不同的业务逻辑代码混杂到一个方法中, 导致代码变得很难以维护 (诸如: 在组件被挂载的生命周期中, 可能主要注册监听, 可能需要发送网络请求等)
- 但是在类组件中共享数据是非常繁琐的, 需要借助Context或者Redux等
- 所以当应用程序变得复杂时, 类组件就会变得非常复杂, 非常难以维护
-
3.如何使用 hooks
Hook的使用我们无需额外安装任何第三方库, 因为它就是React的一部分
- Hook只能在函数组件中使用, 不能在类组件,或者函数组件之外的地方使用
- Hook只能在函数最外层调用, 不要在循环、条件判断或者子函数中调用
useState(保存组件状态)
const [state, setState] = useState(initialState)const [ageState, setAgeState] = useState(18);function incrementAge() {// setAgeState(ageState + 10);// setAgeState(ageState + 10);// setAgeState(ageState + 10);setAgeState((preAgeState)=>preAgeState + 10);}<p>{ageState}</p><button onClick={()=>{incrementAge()}}>增加</button>
useEffect(处理副作用)和 useLayoutEffect (同步执行副作用)
1.什么是 useEffect hooks?
可以把 useEffect 看作 componentDidMount, componentDidUpdate 和 componentWillUnmount 这三个生命周期的组合
2.useEffect Hook特点?
可以设置依赖, 只有依赖发生变化的时候才执行 ``` useEffect(() => { //effect return () => { // cleanup } }, [依赖的状态;空数组,表示不依赖])
useEffect(()=>{ // componentDidMount // componentDidUpdate console.log(‘组件被挂载或者组件更新完成’); return ()=>{ // componentWillUnmount console.log(‘组件即将被卸载’); }
});-----------------------useEffect(()=>{// 组件被挂载console.log('修改DOM');});useEffect(()=>{// 组件被挂载console.log('注册监听');return ()=>{console.log('移出监听');}});useEffect(()=>{console.log('发送网络请求');});
**不要对 Dependencies 撒谎,如果你明明使用了某个变量,却没有申明在依赖中,你等于向react撒了谎,后果就是,当依赖的变量改变时,useEffect 也不会再次执行 ,eslint会报警告**<a name="NIWSm"></a>#### useEffect 和 useLayoutEffect 的区别```javascript区别是 useLayouEffect 是同步执行, 会在DOM 更新完成后立即执行,但是会在浏览器进行任何绘制之前运行完成,阻塞了浏览器的绘制,跟class写法的componentDidMount和componentDidUpdate(render之后,立即执行)类似,都是同步,useEffect 是异步,不会block,browser, painting, 性能更好一点
useContext Hook
useContext相当于 类组件中的 static contextType = Context
useCallback(记忆函数)
useCallback用于优化代码, 可以让对应的函数只有在依赖发生变化时才重新定义
- 防止因为组件重新渲染,导致方法被重创建,起到缓存作用,只有第二个参数 变化了,才重新声明一次 ```javascript var handleClick = useCallback( () =>{ console.log(name) }, [name])
//只有name改变后, 这个函数才会重新声明一次 //如果传入空数组, 那么就是第一次创建后就被缓存,如果name 后期改变了,拿到的还是老的name //如果不传第二个参数,每次都会重新声明一次,拿到的就是最新的name
<a name="nvcyd"></a>#### useMemo Hook- useMemo用于优化代码, 可以让对应的函数只有在依赖发生变化时才返回新的值
// 以下代码的作用: 只要countState没有发生变化, 那么useCallback返回的永远都是同一个函数/*function useCallback(fn, arr){return useMemo(()=>{return fn;}, arr);}-----------------const decrement = useCallback(()=>{setCountState(countState - 1);}, [countState]);-----------------
// 以下代码的作用: 只要countState没有发生变化, 那么useMemo返回的永远都是同一个值 const decrement = useMemo(()=>{ return ()=>{ setCountState(countState - 1); }; }, [countState]);
<a name="F6qAI"></a>#### useRef (保存引用值)```javascriptconst myswiper = useRef(null);<Swiper ref = {myswiper} />
useReducer 和 useContext(减少组件层级)
import React from 'react'var GlobalConter = React.createContext()//注意 此时的 reducer 返回值是一个对象 {isShow: false . list: []}function App(props) {let [] = useReducer(reducer, { isShow: true, list: [] })return <GlobalContext.Provider value={(dispatch)}><div>{ state.isShow? <div >我是选项卡</div> :null }{props.children}</div></GlobalContext.Provider> }}function Detail(){var {dispatch} = useContext(GlobalContext)useEffect(() => {//隐藏 dispatch({type:"Hide",payload:false})return () => {//显示 dispatch({type:"Show",payload:true })};}, [])return <div>detail</div>}
redux-react-hook 无缝使用原来的 redux,和中间件 promise,thunk,saga
自定义 hooks

