React Hooks簡單業務場景實戰(非源碼解讀)

前言

React Hooks 是React 16.7.0-alpha 版本推出的新特性。從 16.8.0 開始,React更穩定的支持了這一新特性。html

它可讓你在不編寫 class 的狀況下使用 state 以及其餘的 React 特性。react

注意:React 16.8.0 是第一個支持 Hook 的版本。升級時,請注意更新全部的 package,包括 React DOM。React Native 將在下一個穩定版本中支持 Hook。redux

若是說promise是JavaScript異步的終極解決方案,那麼React Hooks從某種意義上來講,也是react狀態管理的終極解決方案。數組

爲何用 React Hooks?與其餘狀態管理方案有什麼區別?

在react hooks,react態管理方案主要有以下2種:promise

這兩種狀態解決方案其實已經很不錯,能夠知足絕大多數狀態共享的業務場景。 固然,像FB這樣優秀的團隊優秀的人總喜歡鑽研,不斷優化。認爲這兩種狀態解決方案嵌套太多,不少業務邏輯能夠抽象出來。不只僅是共享狀態就完事了,還得共享出處理邏輯。爲了減小沒必要要的組件嵌套寫法,實現更扁平、顆粒化的狀態 + 邏輯的複用,因而便推出了 React Hooksbash

關於react hooks,具體能夠多看看React Hooks官方文檔,理解會更深。異步

業務實戰1:實現一個簡單的顯示隱藏彈出框

一、基於 render-props實現:函數

// 將父組建的 on狀態 和toggle 事件,共享給嵌套下的子組件
function App() {
 return (
   <Toggle initial={false}>
     {({ on, toggle }) => (
       <Button type="primary" onClick={toggle}> Open Modal </Button>
       <Modal visible={on} onOk={toggle} onCancel={toggle} />
     )}
   </Toggle>
 )
}
複製代碼

二、用react hooks實現學習

import React, { useState } from 'react';

function Example() {
  // 聲明一個新的叫作 「visible」 的 state 變量
  const [visible, setVisible] = useState(false);

  return (
    <div>
      <Modal onClick={() => setVisible(!visible)}>
        Click me
      </Modal>
    </div>
  );
}
複製代碼

業務實戰2: 接收傳入props後立馬更新自有的State狀態(received passed props and updated)

function Avatar(props) {
 const [user, setUser] = React.useState({...props.user}); // 這裏僅僅是給了一個初始值,僅第一次渲染的時候生效,後續都不會再更新了。

 // 用useEffect,第二個參數傳入一個數組字段props.user,
 // 表示每次只要傳入的props.user有變化,那麼就觸發setUser這個操做更新狀態。
 React.useEffect(() => {
     setUser(props.user);
 }, [props.user])

 return user.avatar ? 
        (<img src={user.avatar}/>)
       : (<p>Loading...</p>);
}
複製代碼

由上述例子能夠看到,咱們用到了useEffect這個hooks。優化

Effect Hook 可讓你在函數組件中執行反作用操做

什麼叫反作用呢? 數據獲取,設置訂閱以及手動更改 React 組件中的 DOM 都屬於反作用。

若是實在理解不了反作用,你能夠理解爲,在咱們在寫傳統的react class組件裏面的生命週期鉤子函數componentDidMount,componentDidUpdate 和 componentWillUnmount 這三個函數的組合中處理的相關邏輯,就是反作用。

也就是說,任何你想在頁面首次加載完(componentDidMount),後續每次更新完(componentDidUpdate),亦或者是組件卸載前(componentWillUnmount),這三個勾子中加入你本身的邏輯處理,就得用到useEffect

業務實戰3:顯示後,倒計時自動隱藏(與setInterval結合)

業務場景具體以下:實現一個倒計時30秒,每秒鐘減1,而後倒計時完畢這個組件自動隱藏。

function App() {
  const [count, setCount] = useState(30);
  useEffect(() => {
    setInterval(() => {
      setCount(count - 1);
    }, 1000);
  });
  return <div className="App">{count}</div>;
}
複製代碼

看看上述的寫法,本身運行一下就只知道了,確定是大錯特錯的。 最基本的,setInterval這個刪除定時器都沒有作相關處理。 其次,每次都會生成不一樣都setInterval實例。那麼如何加以控制呢?

來看看正確都寫法,這裏要用到useRef這種類型都hooks了。

function App(props){
    const [visible,setVisible] = useState(false);// 初始化值爲false,隱藏
    const [count,setCount] = useState(0); // 倒計時字段,初始值爲0
    // 明肯定時器要作什麼:咱們這裏是每秒 -1,小於等於0的時候就自動給隱藏
    // 同時,本此的跟新跟下次的渲染更新要共享狀態,記住上次更新這個count減到哪裏了
    // 基於上述問題,咱們可使用以下方案:
    // 聲明一個useRef對象,初始化爲null
    const intervalCb = useRef(null); 
    useEffect(()=>{
      // useRef 對象有一個current屬性,能夠給它賦值爲一個函數
      intervalCb.current = () => { 
      if(count  <= 0){
        setVisible(false);
      }else{
        setCount(count - 1);
      }    
    };   
    })
    
    // 在componentDidMount中設置一個定時器
    useEffect(()=>{
        function itvFn(){
            // 在此前,定時器的回調函數已經聲明,這裏能夠直接調用
            intervalCb.current(); 
        }
        const itvId = window.setInterval(itvFn,1000);
        // return 一個回調函數,表示清除處理
        return () => window.clearInterval(itvId);
    },[]) // 傳入要監聽的對象,空數組表示只監聽一次,至關於didMounted
}

return (<div className={visible}>
        {count}
    </div>)
}
複製代碼

關於useRef 更多的請看useRef官方文檔

業務實戰4: 自定義hooks

基於上述setInterval的業務功能實現,咱們簡單的來寫一個自定義的hooks

export default function useInterval(callback) {
 const savedCallback = useRef();

 useEffect(() => {
   savedCallback.current = callback;
 });

 useEffect(() => {
   function tick() {
     savedCallback.current();
   }

   let id = setInterval(tick, 1000);
   return () => clearInterval(id);
 }, []);
}
複製代碼

而後在你須要用到的地方引入:

import useInterval from 'xx/self_hooks';

function App(){
   useInterval(()=>{
       // ... 跟useEffect寫法相似,目前只支持傳入一個function類型的參數,若是要接收多個參數,那麼在自定義hooks那裏去自行處理一下。
   })
}
複製代碼

關於自定義hooks,更多請查看自定義hooks

暫結

關於react hooks 簡單的使用,此篇就暫時寫到這裏,固然,複雜一點的,可使用useReducer、useContext和useEffect代替Redux方案。後續咱們應該單獨來研究這塊。 回顧一下,如何才能說咱們會用react hooks 呢?

  • 第1、明白概念,幹什麼用的,解決哪些痛點?
  • 第2、useEffect傳入幾個參數?分表表示聲明?useRef做用是什麼?這些能夠解決咱們基本的業務需求。
  • 第3、useReducer、useContext 怎麼替換 redux?
  • 讀源碼,搞清楚爲何useEffect不能卸載if嵌套中等之類的問題?

今天先把問題拋出,後續按照這個,按部就班的學習掌握react hooks。

相關文章
相關標籤/搜索