來自《ReactHooks與Immutable》小冊作者’神三元’的靈魂拷問

NO IMAGE

事情經過

事情的經過是這樣:大家最近可能經常會見到掘金上有個廣告👇

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

然後我看了評價感覺好像挺不錯的,就買了(反正也不貴),加群了以後感覺作者很用心,不過最近項目一直在用Vue做PC端,就沒怎麼看這個小冊,尋思忙完這段時間,過年的時候看。
但是就在這時我突然注意到了三元老師在推薦immer以後就有好多人在問immer是啥?

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問
來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

心血來潮的我決定是時候要給大家好好科普一下了,這麼好用的東西應該儘快讓大家都上手啊,不然作者心灰意冷了不繼續維護了怎麼辦?於是我寫了一篇文章:2020要用immer來代替immutable優化你的React項目
然後我發到了群裡,並@了三元老師:

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

正當我暗自得意的時候他突然給我來了個靈魂拷問:

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問
來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問
來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

雖然最後他說了immer更好用,但是我卻開心不起來了,因為他問了我一個問題我沒有回答上來:useImmer有什麼優勢?(因為我的那篇文章裡寫了用useImmer代替useState)👇

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

寫文章的時候是參考的useImmer官方文檔,這個文檔是這麼寫的:

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

翻譯:useImmer(initialState)和useState非常相似,這個方法返回一個數組,數組中第一個值是當前的state,第二個值是一個更新函數,更新函數接受一個函數來作為參數,這個函數的參數可以非常自由的去更改,當函數執行完之後將會生成一個不可變數據作為新的state

當時我並沒有仔細的看這句話,注意力都集中在他文檔的那個小案例上了,沒有深入的去思考,結果被三元老師一語中的點醒了我:useImmer和useState相比它的優勢到底在哪?

前兩天一直在加班忙項目,甚至連2020年的第一天都在加班-.-! 也沒時間去想這些,今天忙完了突然想起這件事,於是又去仔細看了一眼,終於明白了它比useState好在哪!

更加便捷的存儲及修改state數據

Hooks上市之前我們是這麼定義state的:

state = {
people: [
{
name: '馬雲',
englishName: 'Jack Ma'
},
{
name: '馬化騰',
englishName: 'Pony Ma'
},
{
name: '李彥宏',
englishName: 'Robin Li'
}
]
}

這種情況下如果用 setState({…}) 這種形式的話修改數據的話會比較麻煩,所以推薦函數式寫法:

this.setState(state => {
state.people[2].englishName = 'Robin Lee'
return {...state}
});

函數式setState寫法要求每次都返回一個新的引用,不過自從有了hooks組件定義數據就不能再這麼定義了,假如你要是還像以前一樣那麼寫:

const [state, setState] = useState({
people: [
{
name: '馬雲',
englishName: 'Jack Ma'
},
{
name: '馬化騰',
englishName: 'Pony Ma'
},
{
name: '李彥宏',
englishName: 'Robin Li'
}
]
});

那麼你的setState就不太好改了,相信用過React Hooks的小夥伴們都能懂,而且這也不是被推薦的寫法,一般來說我們會儘可能的細分:

const [jack, setJack] = useState({
name: '馬雲',
englishName: 'Jack Ma'
});
const [pony, setPony] = useState({
name: '馬化騰',
englishName: 'Pony Ma''
});
const [robin, setRobin] = useState({
name: '李彥宏',
englishName: 'Robin Li'
});

這樣的話修改數據就方便多了,粒度也更細膩,但是就是寫起來麻煩、不夠直觀、代碼量也更多,尤其是當你的數據量比較大、或者嵌套層級比較深的情況下那簡直就是一場災難。那麼怎麼樣才能既像以前setState那樣方便快捷,同時又能使用函數式組件呢?聰明的朋友們應該猜也猜到了:useImmer
來看看useImmer是怎麼撰寫上述邏輯的:

// 定義
const [state, setState] = useImmer({
people: [
{
name: '馬雲',
englishName: 'Jack Ma'
},
{
name: '馬化騰',
englishName: 'Pony Ma'
},
{
name: '李彥宏',
englishName: 'Robin Li'
}
]
})
// 修改
setState(state => {state.people[2].name = 'Robin Lee'})

無論嵌套層級多麼深,無論數據有多麼複雜,useImmer總能讓你找到當年 this.setState(state => state.people[2].name = ‘Robin Lee’) 的感覺,但是不同之處除了一個要用 this. 而另一個不用以外還有一個需要注意的地方:

原生的setState直接可以當作返回值,而這個useImmer生成的盜版useState修改後的值不能被直接當作返回值返回,所以需要在函數體外面有大括號。
當然也可以自定義返回值,返回什麼值就會更新成什麼值。

更具體的用法可以參照:2020要用immer來代替immutable優化你的React項目

手動@神三元

寫到這裡已經接近尾聲了,這次寫完了我要繼續發群裡@三元老師,看看這次他還會不會覺得useImmer這個鉤子函數沒有卵用了(點贊多的話後續我會繼續更新文章發三元老師對話的截圖)順便免費給三元先生打個廣告:React Hooks 與 Immutable 數據流實戰

行了不扯淡了,喜歡我文章的朋友記得點關注!

後續

來自《ReactHooks與Immutable》小冊作者'神三元'的靈魂拷問

三元老師在這裡道出了useImmer的使用場景,如果大家的業務場景與三元老師所說的用hooks代替redux場景類似,就可以在項目中試試這個神奇的hook!

相關文章

【學習總結】TCP協議理解

浪到飛起的前端女程序員的2019|年度徵文

[突破前端面試]——Promise&&Async/Await

認真生活,快樂工作|年度總結系列