React哲學:一切皆組件react
類組件ajax
class Counter extends Component {
render () {
return "Hello World"
}
}
複製代碼
函數組件編程
const Counter = () => {
return "Hello World"
}
複製代碼
爲何說函數式組件更優?數組
有hooks以前,爲何React須要類組件?性能優化
class Counter extends Component {
state = {
count: 0
}
}
複製代碼
shouldComponentUpdate () { // 減小render渲染
return true
}
複製代碼
反作用:調用ajax等bash
純函數:每次輸入的參數同樣,那麼每次返回的結果都相同。不要改全局變量,不要作ajax請求,不要去作異步操做等dom
componentDidMount () {
fetchAPI().then(res => {
this.setState({count: res})
})
}
複製代碼
可否讓函數組件擁有這些功能?異步
const Counter = () => {
return `
想擁有,但是我沒辦法擁有狀態,也沒有生命週期函數,更不要說反作用操做了
`
}
複製代碼
Hooks擁有了這些功能函數式編程
useState 狀態管理
useEffect 生命週期函數
useContext
等等...
複製代碼
useState: 在函數中管理狀態
const Counter = () => {
const [count, setCount] = useState(0) // 解構 初始值0
const increment = () => setCount( count + 1 )
return (
<>
<h1>{count}</h1>
<button onClick={increment}>+</button>
</>
)
}
複製代碼
useState的返回值是什麼?
const [count, setCount] = useState(0)
能夠改成下面的寫法:
const state = useState(0)
const count = state[0]
const setCount = state[1]
複製代碼
HoC : Higher order Component(With開頭)
有了useState這個hook以後,就能夠在組件裏管理狀態了
useState 通常寫在函數的最上面
useState:返回結果能夠任意取名
const [count, setCount] = useState(0)
也可寫成
const [count, updateCount] = useState(0)
useState是怎麼作到的?
想象一下React爲每一次useState調用分配一個「空間」
React經過useState調用順序辨別各個「空間」,很簡單,就是經過調用順序來區分的!
複製代碼
useState執行順序必須一致!
不能寫在if判斷裏,以下
const Counter = () => {
const [count, setCount] = useState(0)
if (count % 2 === 0) {
const [bar, setBar] = useState(null) // 不能這麼寫
}
const [foo, setFoo] = useState("foo")
}
const [count, setCount] = useState(0) // 兩個useState 根據調用順序區分
const [name, setName] = useState("Fruit Bro") // 兩個useState 根據調用順序區分
setCount(count + 1)
setCount也是異步的,是setState的變種!
複製代碼
useEffect:有機會作反作用操做
componentDidMount 用於在mount過程結束時的反作用
componentDidUpdate 用於在update過程結束時的反作用
useEffect = componentDidMount + componentDidUpdate
複製代碼
useEffect模擬componentDidMount
useEffect(() => {
// 每次mount或update都會調用到這裏
})
useEffect(() => {
// 只有mount時調用這裏
},[]) // []表明依賴的數據
複製代碼
useEffect模擬componentDidUnmount
useEffect(() => {
// 只有mount時調用這裏
return () => {
// 只有unmount時調用這裏
}
},[])
複製代碼
hooks特有而類組件沒有的是componentDidUnupdate,相似componentDidUnmount
useEffect模擬componentDidUpdate
const mounted = useRef() // useRef()無論調用多少次,返回的結果徹底是同樣的
useEffect(() => {
if (!mounted.current) {
// 初次mounted,其實有用的就是current
mounted.current = true
} else {
// do componentDidUpdate logic
}
})
複製代碼
ref能夠訪問真正的dom,但在React中,是很是介意直接操做真實DOM的,所以用vitural dom
注意:每一次渲染都有獨立的props和state,每一次渲染使用hooks,函數組件的每一次渲染,不管是mount仍是update,無論是第幾回update,它都有獨立的props和state
const Counter = () => {
const [count, setCount] = useState(0)
const onClick = () => {
setCount(count + 1)
setTimeout(() => {
// 返回0的緣由,初次爲0,只有再次渲染的時候count纔會爲1,而每次渲染都有獨立的props和state,所以新的渲染不會影響上一次的值
alert(count) // 0 每一次新的執行就是一次新的開始
}, 1000)
}
return (
<>
<h1>{count}</h1>
<button onClick={onClick}>+</button>
</>
)
}
複製代碼
useContext: 簡化Context的使用
Hooks以前
<Context.Consumer>
{contextValue => <h1>{contextValue}</h1>}
</Context.Consumer>
Hooks以後
const contextValue = useContext(Context)
<h1>{contextValue}</h1>
複製代碼
Hooks的好處
下降了組件的複雜性
1.1 徹底使用函數組件
1.2 無需生命週期函數
1.3 更好的狀態管理
更好的代碼重用性
2.1 傳統的代碼重用方式 組件、高階組件(HoC)、render props模式
2.2 Hooks下的代碼重用方式:函數
定製Hooks: 函數形式的代碼重用
// Beacon 計數
const useBeacon = () => {
const [renderCount, setRenderCount] = useState(0)
useEffect(() => {
sendBeacon()
})
}
// 重用
const Foo = () => {
useBeacon();
...
}
const Bar = () => {
useBeacon();
...
}
複製代碼
React v16.8.0開始正式支持Hooks
原有類組件功能依然支持
業界趨勢將是向函數組件傾斜
遷移策略
瞭解Hooks
對新組建使用Hooks
逐步替換原有類組件
hooks如何處理類組件的shouldComponentUpdate來作性能優化 memo
若有錯誤,歡迎指正!謝謝!