這篇文章主要介紹“怎么理解React hooks的渲染邏輯”,在日常操作中,相信很多人在怎么理解React hooks的渲染邏輯問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解React hooks的渲染邏輯”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
創(chuàng)新互聯(lián)專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站設(shè)計、做網(wǎng)站、寧陵網(wǎng)絡(luò)推廣、小程序開發(fā)、寧陵網(wǎng)絡(luò)營銷、寧陵企業(yè)策劃、寧陵品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎;創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供寧陵建站搭建服務(wù),24小時服務(wù)熱線:028-86922220,官方網(wǎng)址:m.rwnh.cn
由于項目環(huán)境比較復(fù)雜,如果是純class組件,那么就是component、pureComponent、shouldComponentUpdate之類的控制一下是否重新渲染,但是hooks似乎更多場景,接下來一一攻破。
場景一 ,父組件使用hooks,子組件使用class Component
父組件
export default function Test() { const [state, setState] = useState({ a: 1, b: 1, c: 1 }); const [value, setValue] = useState(11); return ( <div> <div> state{state.a},{state.b} </div> <Button type="default" onClick={() => { //@ts-ignore setState({ a: 2, b: 1 }); //@ts-ignore setState({ a: 2, b: 2 }); console.log(state, 'state'); }} > 測試 </Button> <hr /> <div>value{value}</div> <Button type="default" onClick={() => { setValue(value + 1); }} > 測試 </Button> <Demo value={state} /> </div> ); }
子組件
export default class App extends React.Component<Props> { render() { const { props } = this; console.log('demo render'); return ( <div> {props.value.a},{props.value.b} </div> ); } }
結(jié)果每次點擊圖中的測試按鈕,子組件Demo都會重新render:
總結(jié):父組件(hook)每次更新,都會導(dǎo)出一個新的state和value對象,子組件肯定會更新(如果不做特殊處理)
場景二,父組件使用hooks,子組件使用class PureComponent
父組件代碼跟上面一樣,子組件使用PureComponent:
export default function Test() { const [state, setState] = useState({ a: 1, b: 1, c: 1 }); const [value, setValue] = useState(11); return ( <div> <div> state{state.a},{state.b} </div> <Button type="default" onClick={() => { //@ts-ignore setState({ a: 2, b: 1 }); //@ts-ignore setState({ a: 2, b: 2 }); console.log(state, 'state'); }} > 測試 </Button> <hr /> <div>value{value}</div> <Button type="default" onClick={() => { setValue(value + 1); }} > 測試 </Button> <Demo value={state} /> </div> ); }
子組件使用PureComponent:
export default class App extends React.PureComponent<Props> { render() { const { props } = this; console.log('demo render'); return ( <div> {props.value.a},{props.value.b} </div> ); } }
結(jié)果子組件依舊會每次都重新render:
總結(jié):結(jié)論同上,確實是依賴的props改變了,因為父組件是hook模式,每次更新都是直接導(dǎo)出新的value和state.
場景三,搞懂hook的setState跟class組件setState有什么不一樣
理論:class的setState,如果你傳入的是對象,那么就會被異步合并,如果傳入的是函數(shù),那么就會立馬執(zhí)行替換,而hook的setState是直接替換,那么setState在hook中是異步還是同步呢?
實踐:
組件A:
export default function Test() { const [state, setState] = useState({ a: 1, b: 1, c: 1 }); const [value, setValue] = useState(11); return ( <div> <div> state{state.a},{state.b},{state.c} </div> <Button type="default" onClick={() => { //@ts-ignore setState({ a: 2 }); //@ts-ignore setState({ b: 2 }); console.log(state, 'state'); }} > 測試 </Button> <hr /> <div>value{value}</div> <Button type="default" onClick={() => { setValue(value + 1); }} > 測試 </Button> <Demo value={state} /> </div> ); }
我將setState里兩次分別設(shè)置了state的值為{a:2},{b:2},那么是合并,那么我最終得到state應(yīng)該是{a:2,b:2,c:1},如果是替換,那么最后得到的state是{b:2}
結(jié)果:
點擊測試按鈕后,state變成了{(lán)b:2},整個value被替換成了{(lán)b:2}
結(jié)論:hook的setState是直接替換,而不是合并
場景四 , 父組件使用class,子組件使用hook
父組件:
export default class App extends React.PureComponent { state = { count: 1, }; onClick = () => { const { count } = this.state; this.setState({ count: count + 1, }); }; render() { const { count } = this.state; console.log('father render'); return ( <div> <Demo count={count} /> <Button onClick={this.onClick}>測試</Button> </div> ); } }
子組件:
interface Props { count: number; } export default function App(props: Props) { console.log(props, 'props'); return <div>{props.count}</div>; }
邏輯:父組件(class組件)調(diào)用setState,刷新自身,然后傳遞給hooks子組件,然后自組件重新調(diào)用,更新
場景五
但是我此時需要想實現(xiàn)一個class 組件的 PureComponent一樣的效果,需要用到React.memo
修改父組件代碼為:
export default class App extends React.PureComponent { state = { count: 1, value: 1, }; onClick = () => { const { value } = this.state; this.setState({ count: value + 1, }); }; render() { const { count, value } = this.state; console.log('father render'); return ( <div> <Demo count={count} /> {value} <Button onClick={this.onClick}>測試</Button> </div> ); } }
子組件加入memo,代碼修改為:
import React, { useState, memo } from 'react'; interface Props { count: number; } function App(props: Props) { console.log(props, 'props'); return <div>{props.count}</div>; } export default memo(App);
此時邏輯:class組件改變了自身的state,自己刷新自己,由上而下,傳遞了一個沒有變化的props給hooks組件,hooks組件使用了memo包裹自己。
結(jié)果:
我們使用了memo實現(xiàn)了PureComponent的效果,淺比較了一次
場景六,hook,setState每次都是相同的值
export default class App extends React.PureComponent { state = { count: 1, value: 1, }; onClick = () => { const { value } = this.state; this.setState({ value: 1, }); }; render() { const { count, value } = this.state; console.log('father render'); return ( <div> <Demo count={count} /> {value} <Button onClick={this.onClick}>測試</Button> </div> ); } }
結(jié)果:由于每次設(shè)置的值都是一樣的(都是1),hooks不會更新,同class
場景七,父組件和子組件都使用hook
父組件傳入count給子組件
export default function Father() { const [count, setCount] = useState(1); const [value, setValue] = useState(1); console.log('father render') return ( <div> <Demo count={count} /> <div>value{value}</div> <Button onClick={() => { setValue(value + 1); }} > 測試 </Button> </div> ); }
子組件使用count
export default function App(props: Props) { console.log(props, 'props'); return <div>{props.count}</div>; }
結(jié)果:每次點擊測試,都會導(dǎo)致子組件重新render
子組件加入memo
function App(props: Props) { console.log(props, 'props'); return <div>{props.count}</div>; } export default memo(App);
結(jié)果:
子組件并沒有觸發(fā)更新
這里跟第一個案例class的PureComponent不一樣,第一個案例class的PureComponent子組件此時會重新render,是因為父組件hooks確實每次更新都會導(dǎo)出新的value和state。這里是調(diào)用了一次,設(shè)置的都是相同的state.所以此時不更新
場景八,父組件hook,子組件hook,使用useCallback緩存函數(shù)
父組件:
export default function App() { const [count1, setCount1] = useState(0); const [count2, setCount2] = useState(0); const handleClickButton1 = () => { setCount1(count1 + 1); }; const handleClickButton2 = useCallback(() => { setCount2(count2 + 1); }, [count2]); return ( <div> <div> <Button onClickButton={handleClickButton1}>Button1</Button> </div> <div> <Button onClickButton={handleClickButton2}>Button2</Button> </div> </div> ); }
子組件:
import React from 'react'; const Button = (props: any) => { const { onClickButton, children } = props; return ( <> <button onClick={onClickButton}>{children}</button> <span>{Math.random()}</span> </> ); }; export default React.memo(Button);
結(jié)果:雖然我們使用了memo.但是點擊demo1,只有demo1后面的數(shù)字改變了,demo2沒有改變,點擊demo2,兩個數(shù)字都改變了。
那么我們不使用useCallback看看
父組件修改代碼,去掉useCallback
export default function App() { const [count1, setCount1] = useState(0); const [count2, setCount2] = useState(0); const handleClickButton1 = () => { setCount1(count1 + 1); }; const handleClickButton2 = () => { setCount2(count2+ 1); }; return ( <div> <div> <Demo onClickButton={handleClickButton1}>Demo1</Demo> </div> <div> <Demo onClickButton={handleClickButton2}>Demo</Demo> </div> </div> ); }
子組件代碼不變,結(jié)果此時每次都會兩個數(shù)字都會跟著變。
官方對useCallback的解釋:
就是返回一個函數(shù),只有在依賴項發(fā)生變化的時候才會更新(返回一個新的函數(shù))
結(jié)論:
我們聲明的 handleClickButton1 是直接定義了一個方法,這也就導(dǎo)致只要是父組件重新渲染(狀態(tài)或者props更新)就會導(dǎo)致這里聲明出一個新的方法,新的方法和舊的方法盡管長的一樣,但是依舊是兩個不同的對象,React.memo 對比后發(fā)現(xiàn)對象 props 改變,就重新渲染了。
const a =()=>{} const b =()=>{} a===b //false
這個道理大家都懂,不解釋了
場景九,去掉依賴數(shù)組中的count2字段
import React, { useState, useCallback } from 'react'; import Demo from './Demo'; export default function App() { const [count2, setCount2] = useState(0); const handleClickButton2 = useCallback(() => { setCount2(count2 + 1); }, []); return ( <Demo count={count2} onClickButton={handleClickButton2} >測試</Demo> ); }
這樣count2的值永遠(yuǎn)都是0,那么這個組件就不會重導(dǎo)出setCount2這個方法,handleClickButton2這個函數(shù)永遠(yuǎn)不會變化,Button只會更新一次,就是Demo組件接受到的props從0到1到的時候.繼續(xù)點擊,count2也是0,但是props有一次從0-1的過程導(dǎo)致Demo子組件被更新,不過count2始終是0,這非常關(guān)鍵
場景十,使用useMemo,緩存對象,達(dá)到useCallback的效果
使用前
export default function App() { const [count, setCount] = useState(0); const [value, setValue] = useState(0); const userInfo = { age: count, name: 'Jace', }; return ( <div> <div> <Demo userInfo={userInfo} /> </div> <div> {value} <Button onClick={() => { setValue(value + 1); }} ></Button> </div> </div> ); }
子組件使用了memo,沒有依賴value,只是依賴了count.
但是結(jié)果每次父組件修改了value的值后,雖然子組件沒有依賴value,而且使用了memo包裹,還是每次都重新渲染了
import React from 'react'; const Button = (props: any) => { const { userInfo } = props; console.log('sub render'); return ( <> <span>{userInfo.count}</span> </> ); }; export default React.memo(Button);
使用后useMemo
const [count, setCount] = useState(0); const obj = useMemo(() => { return { name: "Peter", age: count }; }, [count]); return <Demo obj={obj}>
很明顯,第一種方式,如果每次hook組件更新,那么hook就會導(dǎo)出一個新的count,const 就會聲明一個新的obj對象,即使用了memo包裹,也會被認(rèn)為是一個新的對象。
看看第二種的結(jié)果:
父組件更新,沒有再影響到子組件了。
到此,關(guān)于“怎么理解React hooks的渲染邏輯”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
網(wǎng)頁名稱:怎么理解Reacthooks的渲染邏輯
網(wǎng)站地址:http://m.rwnh.cn/article16/pdiddg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、網(wǎng)站排名、搜索引擎優(yōu)化、網(wǎng)站設(shè)計公司、網(wǎng)站建設(shè)、云服務(wù)器
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)