React hooks整理:
- 会有 Capture Value 特性
- 推荐配合
eslint-plugin-react-hooks
使用
- useEffect:
- useEffect 依赖一个空数组的时候,会记住 state 的值
useEffect(()=>{
setInterval(() => {
console.log(num)
setNum(num+1)
}, 500);
},[])
- useEffect 依赖的数组里有值时,每次依赖项更新时,会把更新的值传给 effect 并重新执行 effect 里面的代码
useEffect(()=>{
setInterval(() => {
console.log(num)
setNum(num+1)
}, 500);
},[num])
- useEffect 里面不加 return 时,useEffect 中的代码块相当于在 class 组件的 componentDidMount 和 componentDidUpdate 中的代码块;加了 return 后,return 后的代码块相当于 class 组件里的 componentWillUnmount 中的代码块
useEffect(()=>{
const timer = setInterval(() => {
console.log(num)
setNum(num+1)
}, 500);
return ()=>clearInterval(timer)
},[num])
- useRef:
useEffect(()=>{
countRef.current = count
},[count])
useEffect(()=>{
const timer = setInterval(() => {
console.log(countRef)
setCount(countRef.current+1)
}, 500);
return ()=>clearInterval(timer)
},[])
const btnRef = useRef(null)
useEffect(()=>{
const handleClick = ()=>{
setCount(count+1)
}
btnRef.current.addEventListener('click',handleClick,false);
return ()=>{
btnRef.current.removeEventListener('click', handleClick,false);
}
},[count])
return (
<div>
<p>count: {count}</p>
<button ref={btnRef}>+1</button>
</div>
)
- memo: 相当于 pureComponent
import React, {useState, useEffect, useRef, memo} from 'react';
const Child = memo(()=> {
return (
<div>
fffffff
</div>
)
})
import React, {useState, useEffect, useRef, memo} from 'react';
const Child = memo(()=> {
return (
<div>
fffffff
</div>
)
},(prev,next)=>{
return prev.count === next.count
})
const Child = memo((props)=> {
console.log(props)
const date = new Date()
return (
<div>
当前时间:{date.getHours()}: {date.getMinutes()}: {date.getSeconds()}
</div>
)
})
const Parent = ()=> {
const [count, setCount] = useState(0)
const [clickTimeCount, setTimeClickCount] = useState(0)
const timeOption = useMemo(()=>{
return {
clickTimeCount
}
},[clickTimeCount])
return (
<div>
<div>count: {count}</div>
<button onClick={()=>{
setCount(count+1)
}}>+1</button>
<button onClick={()=>{
setTimeClickCount(clickTimeCount+1)
}}>GET CURRENT TIME</button>
<Child count={timeOption}/>
</div>
)
}
import React, {useState, useEffect, useRef, memo, useMemo, useCallback} from 'react';
const Child = memo((props)=> {
console.log(props)
const date = new Date()
return (
<div>
当前时间:{date.getHours()}: {date.getMinutes()}: {date.getSeconds()}
<input type="text" onChange={props.onChange}/>
</div>
)
})
const Parent = ()=> {
const [count, setCount] = useState(0)
const [text, setText] = useState('')
const [clickTimeCount, setTimeClickCount] = useState(0)
const handleOnchange = useCallback( (e)=>{
setText(e.target.value)
},[])
return (
<div>
<div>count: {count}</div>
<div>text: {text}</div>
<button onClick={()=>{
setCount(count+1)
}}>+1</button>
<button onClick={()=>{
setTimeClickCount(clickTimeCount+1)
}}>GET CURRENT TIME</button>
<Child count={clickTimeCount} onChange={handleOnchange}/>
</div>
)
}
- 自定义 hooks: 通用逻辑抽离
import {useState,useEffect} from 'react'
export const useWindowSize = () => {
const [width, setWidth] = useState('0px')
const [height, setHeight] = useState('0px')
useEffect(()=>{
setWidth(document.documentElement.clientWidth+ 'px')
setHeight(document.documentElement.clientHeight+ 'px')
},[])
useEffect(()=>{
const handleResize = ()=>{
setWidth(document.documentElement.clientWidth+ 'px')
setHeight(document.documentElement.clientHeight+ 'px')
}
window.addEventListener('resize',handleResize,false)
return ()=>{
window.removeEventListener('resize',handleResize,false)
}
},[])
return [width, height]
}
import React, {useState, useEffect, useRef, memo, useMemo, useCallback} from 'react';
import {useWindowSize} from './hooks'
const Parent = ()=> {
const [width, height] = useWindowSize()
return (
<div>
size:{width} * {height}
</div>
)
}
function App() {
return (
<div className="App">
<Parent />
</div>
);
}
export default App;
import React, {useReducer,useContext} from 'react';
const Ctx = React.createContext(null)
const reducer = (state,action) => {
switch (action.type) {
case 'ADD':
return state + 1
case 'SUB':
return state - 1
default:
return state
}
}
const Child = ()=>{
const [count, dispatch] = useContext(Ctx)
return (
<div>
child: count: {count}
<button onClick={()=>dispatch({type:'ADD'})}>+1</button>
<button onClick={()=>dispatch({type:'SUB'})}>-1</button>
</div>
)
}
const Parent = ()=> {
const [count, dispatch] = useContext(Ctx)
return (
<div>
Parent: {count}
<Child />
</div>
)
}
function App() {
const [count, dispatch] = useReducer(reducer, 20)
return (
<Ctx.Provider value={[count, dispatch]}>
<div className="App">
<Parent />
</div>
</Ctx.Provider>
);
}
export default App;
- useSelector(mapStateToProps)、useDispatch(mapDispatchToProps):
import React from 'react'
import {useSelector, useDispatch} from 'react-redux'
import {updateName, updateTel} from './action'
export default ()=>{
const formData = useSelector(state => {
console.log(state)
return state.form
})
const dispatch = useDispatch()
return (
<div>
form: <br />
姓名: <input type='text' onChange={e=>{dispatch(updateName(e.target.value))}} /><br />
电话: <input type='tel' onChange={e=>{dispatch(updateTel(e.target.value))}} /><br />
</div>
)
}