久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

簡單的 useState 實(shí)現(xiàn)

 python_lover 2021-09-10

簡單的 useState 實(shí)現(xiàn)

本文寫于 2020 年 10 月 21 日

以下是一段非常簡單的 React 代碼:

const App = () => {
  const [n, setN] = useState(0);
  return (
    <div>
      {n}
      <button onClick={() => setN(x => x + 1)}>+1</button>
    </div>
  );
}

React.render(<App />, rootElement)

這樣的用法和以往的 setState 是有明顯的不同的,,他看起來更像 redux——我們初始化一個(gè) state,,然后 dispatch 一個(gè) action,,再由 reducer 改變 state 后返回新的 state,。

Redux 思想實(shí)現(xiàn) useState

既然我們覺得它像,那我們就來自己實(shí)現(xiàn)一個(gè)吧,。

不熟悉 Redux 思想的同學(xué)請自行閱讀文檔

const useState = (initialValue) => {
  let state = initialValue;
  const dispatch = (newState) => {
    state = newState;
    render(<App />, document.getElementById('root'));
  };
  return [state, dispatch];
};

然后我們用這個(gè)自定義的 useState 代替 React 的 useState——就會發(fā)現(xiàn)我們失敗了,,setN 無論如何都不會有任何反應(yīng)。

這是因?yàn)槲覀兠看沃匦?render 的時(shí)候都重新執(zhí)行了函數(shù),,于是我們總是會重新賦值,。

為什么不會重新賦值,?

對于這段 React 代碼來說,當(dāng)我們第一次運(yùn)行時(shí),,React 會進(jìn)行首次渲染,,即 render(<App />, ...)

在此過程中,,會先調(diào)用 App(),,之后便會得到虛擬 DOM,再創(chuàng)建真實(shí)的 Div,。

當(dāng)我們觸發(fā)點(diǎn)擊事件時(shí),,會調(diào)用 setN,再次 render(),。之后調(diào)用 App(),,然后得到新的虛擬 DOM,進(jìn)行 diff 算法,,根據(jù) diff 算法的結(jié)果去更新新的 Div,。

而不管是第一次渲染,還是第二次調(diào)用,,都會調(diào)用 useState(),。

但是我們寫的是 useState(0) 啊,兩次調(diào)用明明是一樣的代碼,,為何 n 的值不同,?怎么解決這個(gè)問題呢?

很簡單,,閉包嘛,。

const createUseState = () => {
  let state;
  const useState = (initialValue) => {
    if (!state) {
      state = initialValue;
    }
    const dispatch = (newState) => {
      state = newState;
      render(<App />, document.getElementById('root'));
    };
    return [state, dispatch];
  };
};

這樣就解決了重新賦值的問題,。

多次調(diào)用

但是我們需要多次調(diào)用 useState 呀,不可能只用一次的,。

于是我們將 state 改為一個(gè)數(shù)組:const state = [];,。

const createUseState = () => {
  const state = [];
  let index = 0;
  return (initialValue) => {
    state[index] = state[index] || initialValue;
    const currentIndex = index;
    const dispatch = (newState) => {
      state[currentIndex] = newState;
      // 重點(diǎn)
      index = 0;
      ReactDOM.render(
        <React.StrictMode>
          <App />
        </React.StrictMode>,
        rootElement
      );
    };
    return [state[index++], dispatch];
  };
};

我們創(chuàng)建了一個(gè) index 變量來控制索引。它需要我們保證每次重新渲染 App 傳入數(shù)組的元素是一樣的——這就是為什么我們不可以將 useState 寫在 if 判斷中,。

在上述代碼中有一處重點(diǎn),,在于我們需要在每次 set 之后將索引歸零 index = 0

因?yàn)槊看?render 結(jié)束后,,React 都會重新執(zhí)行該函數(shù),。

(完)

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多