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 (保存引用值)
```javascript
const 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