成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React-hooks 簡(jiǎn)介

incredible / 2522人閱讀

摘要:比如在條件判斷中使用,在循環(huán),嵌套函數(shù)中使用,都會(huì)造成執(zhí)行順序不一致的問(wèn)題。而比如定時(shí)器,事件監(jiān)聽(tīng)。第一個(gè)參數(shù)的返回值,會(huì)在組件卸載時(shí)執(zhí)行,相當(dāng)于,可以清理定時(shí)器,移除事件監(jiān)聽(tīng),取消一些訂閱。

什么是 Hooks?
不通過(guò)編寫類組件的情況下,可以在組件內(nèi)部使用狀態(tài)(state) 和其他 React 特性(生命周期,context)的技術(shù)
Hooks 為什么會(huì)出現(xiàn)

在之前的 React 版本中,組件分為兩種:函數(shù)式組件(或無(wú)狀態(tài)組件(StatelessFunctionComponent))和類組件,而函數(shù)式組件是一個(gè)比較的純潔的 props => UI 的輸入、輸出關(guān)系,但是類組件由于有組件自己的內(nèi)部狀態(tài),所以其輸出就由 propsstate 決定,類組件的輸入、輸出關(guān)系就不再那么純潔。同時(shí)也會(huì)帶來(lái)下列問(wèn)題:

狀態(tài)邏輯難以復(fù)用。很多類組件都有一些類似的狀態(tài)邏輯,但是為了重用這些狀態(tài)邏輯,社區(qū)提出了 render props 或者 hoc 這些方案,但是這兩種模式對(duì)組件的侵入性太強(qiáng)。另外,會(huì)產(chǎn)生組件嵌套地獄的問(wèn)題。

大多數(shù)開(kāi)發(fā)者在編寫組件時(shí),不管這個(gè)組件有木有內(nèi)部狀態(tài),會(huì)不會(huì)執(zhí)行生命周期函數(shù),都會(huì)將組件編寫成類組件,后續(xù)迭代可能增加了內(nèi)部狀態(tài),又增加了副作用處理,又在組件中調(diào)用了一些生命周期函數(shù),文件代碼行數(shù)日益增多,最后導(dǎo)致組件中充斥著無(wú)法管理的混亂的狀態(tài)邏輯代碼和各種副作用,各種狀態(tài)邏輯散落在實(shí)例方法和生命周期方法中,維護(hù)性變差,拆分更是難上加難。

在類組件中,需要開(kāi)發(fā)者額外去關(guān)注 this 問(wèn)題,事件監(jiān)聽(tīng)器的添加和移除等等。

State Hook
state hook 提供了一種可以在 function component 中添加狀態(tài)的方式。通過(guò) state hook,可以抽取狀態(tài)邏輯,使組件變得可測(cè)試,可重用。開(kāi)發(fā)者可以在不改變組件層次結(jié)構(gòu)的情況下,去重用狀態(tài)邏輯。更好的實(shí)現(xiàn)關(guān)注點(diǎn)分離。

一個(gè)簡(jiǎn)單的使用 useState 栗子

import React, { useState } from "react";

const StateHook = () => {
  const [count, setCount] = useState(0);

  return (
    

you clicked {count} times

); };

幾點(diǎn)說(shuō)明:

useState 推薦一種更加細(xì)粒度的控制狀態(tài)的方式,即一個(gè)狀態(tài)對(duì)應(yīng)一個(gè)狀態(tài)設(shè)置函數(shù),其接受的參數(shù)將作為這個(gè)狀態(tài)的初始值。其返回一個(gè)長(zhǎng)度為2的元組,第一項(xiàng)為當(dāng)前狀態(tài),第二項(xiàng)為更新函數(shù)。

useState 的執(zhí)行順序在每一次更新渲染時(shí)必須保持一致,否則多個(gè) useState 調(diào)用將不會(huì)得到各自獨(dú)立的狀態(tài),也會(huì)造成狀態(tài)對(duì)應(yīng)混亂。比如在條件判斷中使用 hook,在循環(huán),嵌套函數(shù)中使用 hook,都會(huì)造成 hook 執(zhí)行順序不一致的問(wèn)題。最后導(dǎo)致?tīng)顟B(tài)的混亂。另外,所有的狀態(tài)聲明都應(yīng)該放在函數(shù)頂部,首先聲明。

useStatesetState 的區(qū)別

useStatesetState 進(jìn)行覆蓋式更新,而 setState 則將狀態(tài)進(jìn)行合并式更新。

一個(gè)不正確的栗子

import React, { useState, ChangeEvent } from "react";

const UserForm = () => {
  const [state, setUser] = useState({ name: "", email: "" });

  const { name, email } = state;

  const handleNameChange = (event: ChangeEvent) => {
    const { target: { value: name } } = event;
    // 這里不可以多帶帶的設(shè)置某一個(gè)字段 新的狀態(tài)必須與初始的狀態(tài)類型保持一致
    // 如果只設(shè)置了其中一個(gè)字段,編譯器會(huì)報(bào)錯(cuò),同時(shí)其余的字段也會(huì)丟失
    setUser({ name, email });
  };

  const handleEmailChange = (event: ChangeEvent) => {
    const { target: { value: email } } = event;
    // 這里不可以多帶帶的設(shè)置某一個(gè)字段 新的狀態(tài)必須與初始的狀態(tài)類型保持一致
    setUser({ name, email });
  };

  return (
    <>
        
      
    
  );
}

正確的做法

import React, { useState, ChangeEvent } from "react";

const UserForm = () => {
  // 一個(gè)狀態(tài)對(duì)應(yīng)一個(gè)狀態(tài)更新函數(shù)
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  const handleNameChange = (event: ChangeEvent) => {
    const { target: { value: name } } = event;
    // hear could do some validation
    setName(name);
  };

  const handleEmailChange = (event: ChangeEvent) => {
    const { target: { value: email } } = event;
    // hear could do some validation
    setEmail(email);
  };

  return (
    <>
        
      
    
  );
}
Effect Hook
數(shù)據(jù)獲取,設(shè)置訂閱,手動(dòng)的更改 DOM,都可以稱為副作用,可以將副作用分為兩種,一種是需要清理的,另外一種是不需要清理的。比如網(wǎng)絡(luò)請(qǐng)求,DOM 更改,日志這些副作用都不要清理。而比如定時(shí)器,事件監(jiān)聽(tīng)。

一個(gè)簡(jiǎn)單使用 effect hook 去修改文檔標(biāo)題的栗子。

import React, { useState, useEffect } from "react";

const effectHook = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `you clicked ${count} times`;
  }, [count]);

  return (
    

you clicked {count} times

); };

在調(diào)用 useEffect 后,相當(dāng)于告訴 React 在每一次組件更新完成渲染后,都調(diào)用傳入 useEffect 中的函數(shù),包括初次渲染以及后續(xù)的每一次更新渲染。

幾點(diǎn)說(shuō)明:

useEffect(effectCallback: () => void, deps: any[]) 接收兩個(gè)參數(shù),第二個(gè)參數(shù)依賴項(xiàng)是可選的,表示這個(gè) effect 要依賴哪些值。

有時(shí)候我們并不想每次渲染 effect 都執(zhí)行,只有某些值發(fā)生變化才去執(zhí)行 effect,這個(gè)時(shí)候我們可以指定這個(gè) effect 的依賴列表,可以是一個(gè)也可以幾個(gè),當(dāng)其中列表中的某一個(gè)值發(fā)生變化,effect 才會(huì)執(zhí)行。

第一個(gè)參數(shù)的返回值,會(huì)在組件卸載時(shí)執(zhí)行,相當(dāng)于 componentWillUnmount,可以清理定時(shí)器,移除事件監(jiān)聽(tīng),取消一些訂閱。

當(dāng)?shù)诙€(gè)參數(shù)為一個(gè)空數(shù)組時(shí),相當(dāng)于 componentDidMount 和 componentWillUnmount,表明這個(gè) effect 沒(méi)有任何依賴,只在首次渲染時(shí)執(zhí)行。

Custom Hook

也可以使用 useEffectuseState 實(shí)現(xiàn)自定義 hook。

一個(gè)給 DOM 元素添加事件監(jiān)聽(tīng)器的栗子。

import { useRef, useEffect } from "react";

type EventType = keyof HTMLElementEventMap;
type Handler = (event: Event) => void;

const useEventListener = (
  eventName: EventType,
  handler: Handler,
  element: EventTarget = document
) => {
  // 這里使用 `useRef` 來(lái)保存?zhèn)魅氲谋O(jiān)聽(tīng)器,
  // 在監(jiān)聽(tīng)器變更后,去更新 `useRef` 返回的對(duì)象的 `current` 屬性
  const saveHandler = useRef();

  useEffect(() => {
    saveHandler.current = handler;
  }, [handler]);

  useEffect(() => {
    const supported = element && element.addEventListener;
    if (!supported) {
      return;
    }

    const listener: Handler = (event: Event) => (saveHandler.current as Handler)(event);

    element.addEventListener(eventName, listener);

    return () => {
      element.removeEventListener(eventName, listener);
    };
  }, [eventName, element]);
}

一個(gè)使用 useReducer 來(lái)實(shí)現(xiàn)加、減計(jì)數(shù)器的栗子。這里雖然使用 useReducer 創(chuàng)建了類似 redux 的 功能,但是如果有多個(gè)組件都引用了這個(gè) hook,那么這個(gè) hook 提供的狀態(tài)是相互獨(dú)立、互不影響的,即 useReducer 只提供了狀態(tài)管理,但是并沒(méi)有提供數(shù)據(jù)持久化的功能。redux 卻提供了一種全局維護(hù)同一個(gè)數(shù)據(jù)源的機(jī)制。所以可以利用 useReducerContext 來(lái)實(shí)現(xiàn)數(shù)據(jù)持久化的功能。

import React, { useReducer } from "react";

const INCREMENT = "increment";
const DECREMENT = "decrement";

const initHandle = (initCount) => {
  return { count: initCount };
};

const reducer = (state, action) => {
  switch (action.type) {
    case INCREMENT:
      return { count: state.count + 1 };
    case DECREMENT:
      return { count: state.count - 1 };
    case "reset":
      return { count: action.payload };
    default:
      return state;
  }
};

const Counter = ({ initialCount }) => {
  const [state, dispatch] = useReducer(reducer, initialCount, initHandle);
  const { count } = state;

  return (
    
Counter: {count} j
); };

一個(gè)對(duì)封裝數(shù)據(jù)請(qǐng)求栗子。

import { useState, useEffect } from "react";
import axios, { AxiosRequestConfig } from "axios";

interface RequestError {
  error: null | boolean;
  message: string;
}

const requestError: RequestError = {
  error: null,
  message: "",
};

/**
 * @param url request url
 * @param initValue if initValue changed, the request will send again
 * @param options request config data
 *
 * @returns a object contains response"s data, request loading and request error
 */
const useFetchData = (url: string, initValue: any, options: AxiosRequestConfig = {}) => {
  const [data, saveData] = useState();
  const [loading, updateLoading] = useState(false);
  const [error, updateError] = useState(requestError);

  let ignore = false;

  const fetchData = async () => {
    updateLoading(true);

    const response = await axios(url, options);

    if (!ignore) saveData(response.data);

    updateLoading(false);
  };

  useEffect(() => {
    try {
      fetchData();
    } catch (error) {
      updateError({ error: true, message: error.message });
    }

    return () => {
      ignore = true;
    };
  }, [initValue]);

  return { data, loading, error };
};

export { useFetchData };
Rules of Hook

隨來(lái) hooks 帶來(lái)了新的組件編寫范式,但是下面兩條規(guī)則還是要開(kāi)發(fā)者注意的。

在頂部使用 hook,不要使用 hook 在條件判斷,循環(huán),嵌套函數(shù)。

只在 function component 中使用 hook,或者自定義 hook 中使用 hook, 不要在常規(guī)的 JavaScript 函數(shù)中使用 hook

新的問(wèn)題

hooks 的帶來(lái),雖然解決之前存在的一些問(wèn)題,但是也帶來(lái)了新的問(wèn)題。

異常捕獲。之前的版本中,我們可以用 componentDidCatch 來(lái)捕獲組件作用域內(nèi)的異常,做一些提示。但是在 hooks 中 ,我們只能使用 try {} catch(){} ` 去捕獲,使用姿勢(shì)也比較別扭。

一個(gè)組件若有狀態(tài),則狀態(tài)一旦改變,所有的子組件需要重新渲染。所以一個(gè)有狀態(tài)的組件,應(yīng)該是沒(méi)有子組件的。即 有狀態(tài)的組件不做渲染,有渲染的組件沒(méi)有狀態(tài)

狀態(tài)變更的函數(shù)不支持回調(diào)。this.setState() 中支持第二個(gè)參數(shù),允許我們?cè)跔顟B(tài)變更后,傳入回調(diào)函數(shù)做一些其他事情。但是 useState 不支持。詳見(jiàn)。

參考鏈接
making-sense-of-react-hooks
rehooks
awesome-react-hooks
如何使用useEffect來(lái)獲取數(shù)據(jù)
hooks 是如何工作的
更多關(guān)于 hooks 的討論

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104060.html

相關(guān)文章

  • react-hooks中的一些懵逼點(diǎn)

    摘要:前言一直對(duì)這個(gè)新特性非常感興趣,終于今天有時(shí)間,花了大半天時(shí)間,把的官方教程過(guò)了一遍,收獲頗多,驚嘆這個(gè)新特性真好用,以后開(kāi)發(fā)用這個(gè)怕是要起飛了 前言:一直對(duì)這個(gè)新特性非常感興趣,終于今天有時(shí)間,花了大半天時(shí)間,把 Hooks的官方教程過(guò)了一遍,收獲頗多,驚嘆這個(gè)新特性真 TM 好用,以后開(kāi)發(fā)用這個(gè)怕是要起飛了

    Simon 評(píng)論0 收藏0
  • React Hook 不完全指南

    摘要:使用完成副作用操作,賦值給的函數(shù)會(huì)在組件渲染到屏幕之后。如此很容易產(chǎn)生,并且導(dǎo)致邏輯不一致。同時(shí),這也是很多人將與狀態(tài)管理庫(kù)結(jié)合使用的原因之一。當(dāng)我們通過(guò)的第二個(gè)數(shù)組類型參數(shù),指明當(dāng)前的依賴,就能避免不相關(guān)的執(zhí)行開(kāi)銷了。 前言 本文內(nèi)容大部分參考了 overreacted.io 博客一文,同時(shí)結(jié)合 React Hook 官方 文章,整理并歸納一些筆記和輸出個(gè)人的一些理解 什么是 Hoo...

    Lin_R 評(píng)論0 收藏0
  • Reactv16.7.0-alpha.2 Hooks學(xué)習(xí)

    摘要:的來(lái)源鉤子,顧名思義,為了解決在函數(shù)組件中使用和生命周期,同時(shí)提高業(yè)務(wù)邏輯復(fù)用。函數(shù)組件等同于一個(gè)純的專門用作渲染的函數(shù),我們知道,在函數(shù)組件中,我們無(wú)法使用和生命周期,這也是為了解決的問(wèn)題。 Hooks的來(lái)源 Hooks => 鉤子,顧名思義,為了解決在函數(shù)組件(Function Component)中使用state和生命周期,同時(shí)提高業(yè)務(wù)邏輯復(fù)用。 Function Co...

    superPershing 評(píng)論0 收藏0
  • 基于Taro與typescript開(kāi)發(fā)的網(wǎng)易云音樂(lè)小程序

    摘要:基于與網(wǎng)易云音樂(lè)開(kāi)發(fā),技術(shù)棧主要是目前主要是著重小程序端的展示,主要也是借此項(xiàng)目強(qiáng)化下上述幾個(gè)技術(shù)棧的使用,通過(guò)這個(gè)項(xiàng)目也可以幫助你快速使用開(kāi)發(fā)一個(gè)屬于你自己的小程序地址,感興趣的話可以關(guān)注下,功能會(huì)進(jìn)行持續(xù)完善快速開(kāi)始首先需要在目錄下 基于Taro與網(wǎng)易云音樂(lè)api開(kāi)發(fā),技術(shù)棧主要是:typescript+taro+taro-ui+redux,目前主要是著重小程序端的展示,主要也是借...

    張利勇 評(píng)論0 收藏0
  • react hooks初體驗(yàn)

    摘要:此優(yōu)化有助于避免在每個(gè)渲染上進(jìn)行昂貴的計(jì)算。同樣也是一個(gè)函數(shù),接受兩個(gè)參數(shù),第一個(gè)參數(shù)為函數(shù),第二個(gè)參數(shù)為要比對(duì)的值,返回一個(gè)值。同理,第二個(gè)參數(shù)傳入的值沒(méi)有更新時(shí),不會(huì)執(zhí)行。以上代碼的地址為初體驗(yàn) 什么是Hooks?Hooks是react即將推出的功能,它允許您在不編寫類的情況下使用狀態(tài)和其他React功能。我的理解就是可以用寫無(wú)狀態(tài)組件的方式去編寫擁有狀態(tài)的組件。遺憾的是,正式版1...

    anyway 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<