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