溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

React Hook是什么

發(fā)布時(shí)間:2022-03-22 09:36:41 來(lái)源:億速云 閱讀:219 作者:小新 欄目:web開(kāi)發(fā)

這篇文章主要為大家展示了“React Hook是什么”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“React Hook是什么”這篇文章吧。

react hook有:useState、useEffect、useLayoutEffect、useMemo、useRef、useContext、useReducer、useDebugValue、useImperativeHandle等等。

React Hook是什么

本教程操作環(huán)境:Windows7系統(tǒng)、react17.0.1版、Dell G3電腦。

React Hook是什么?

React官網(wǎng)是這么介紹的: Hook 是 React 16.8 的新增特性。它可以讓你在不編寫(xiě) class 的情況下使用 state 以及其他的 React 特性。

  • 完全可選的你無(wú)需重寫(xiě)任何已有代碼就可以在一些組件中嘗試 Hook。但是如果你不想,你不必現(xiàn)在就去學(xué)習(xí)或使用 Hook。

  • 100% 向后兼容的Hook 不包含任何破壞性改動(dòng)。

  • 現(xiàn)在可用Hook 已發(fā)布于 v16.8.0。

  • 沒(méi)有計(jì)劃從 React 中移除 class你可以在本頁(yè)底部的章節(jié)讀到更多關(guān)于 Hook 的漸進(jìn)策略。

  • Hook 不會(huì)影響你對(duì) React 概念的理解恰恰相反,Hook 為已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命周期。稍后我們將看到,Hook 還提供了一種更強(qiáng)大的方式來(lái)組合他們。


如果對(duì)react還不夠了解建議先看下react官方文檔,寫(xiě)寫(xiě)demo再來(lái)看文章,因?yàn)橛械膔eact基礎(chǔ)的東西我就一筆帶過(guò)不細(xì)說(shuō)。
react 官方文檔 https://zh-hans.reactjs.org/docs/hooks-state.html

React提供的Hook

hook用途
useState設(shè)置和改變state,代替原來(lái)的state和setState
useEffect代替原來(lái)的生命周期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合并版
useLayoutEffect與 useEffect 作用相同,但它會(huì)同步調(diào)用 effect
useMemo控制組件更新條件,可根據(jù)狀態(tài)變化控制方法執(zhí)行,優(yōu)化傳值
useCallbackuseMemo優(yōu)化傳值,usecallback優(yōu)化傳的方法,是否更新
useRef跟以前的ref,一樣,只是更簡(jiǎn)潔了
useContext上下文爺孫及更深組件傳值
useReducer代替原來(lái)redux里的reducer,配合useContext一起使用
useDebugValue在 React 開(kāi)發(fā)者工具中顯示自定義 hook 的標(biāo)簽,調(diào)試使用。
useImperativeHandle可以讓你在使用 ref 時(shí)自定義暴露給父組件的實(shí)例值。

1.useState

import React from 'react';
import './App.css';
//通常的class寫(xiě)法,改變狀態(tài)
class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      hook:'react hook 是真的好用啊'
    }
  }
  changehook = () => {
    this.setState({
      hook:'我改變了react hook 的值'
    })
  }
  render () {
    const { hook } = this.state
    return(
         <header className="App-header">
          {hook}
          <button onClick={this.changehook}>
            改變hook
          </button>
        </header>
      )
  }
}
export  {App}

//函數(shù)式寫(xiě)法,改變狀態(tài)
function App() {
//創(chuàng)建了一個(gè)叫hook的變量,sethook方法可以改變這個(gè)變量,初始值為‘react hook 是真的好用啊’
 const [hook, sethook] = useState("react hook 是真的好用啊");
  return ( 
    <header className="App-header">
      {hook}{/**這里的變量和方法也是可以直接使用的 */}
      <button onClick={() => sethook("我改變了react hook 的值")}>
        改變hook
      </button>
    </header>
  );
}
export  {App}

//箭頭函數(shù)的函數(shù)寫(xiě)法,改變狀態(tài)
export const App = props => {
  const [hook, sethook] = useState("react hook 是真的好用啊");
  return (
    <header className="App-header">
      {hook}
      <button onClick={() => sethook("我改變了react hook 的值")}>
        改變hook
      </button>
    </header>
  );
};

使用方法備注在上面的demo中
看完上面useState的對(duì)比使用,一個(gè)小的demo結(jié)構(gòu)更清晰,代碼更簡(jiǎn)潔,更像寫(xiě)js代碼,運(yùn)用到項(xiàng)目中,那豈不是美滋滋。


2.useEffect & useLayoutEffect

useEffect代替原來(lái)的生命周期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合并版
useEffect( ()=>{ return ()=>{ } } , [ ])

  • 第一個(gè)參數(shù),是函數(shù),默認(rèn)第一次渲染和更新時(shí)都會(huì)觸發(fā),默認(rèn)自帶一個(gè)return ,return一個(gè)函數(shù)表示可以再銷毀之前可以處理些事情

  • 第二個(gè)參數(shù),數(shù)組,空的時(shí)候表示只執(zhí)行一次,更新時(shí)不觸發(fā),里面的參數(shù)是什么,當(dāng)參數(shù)變化時(shí)才會(huì)執(zhí)行useEffect
    useEffect可以多次使用,按照先后順序執(zhí)行
    useLayoutEffect強(qiáng)制useeffect的執(zhí)行為同步,并且先執(zhí)行useLayoutEffect內(nèi)部的函數(shù)

import React, { useState, useEffect, useLayoutEffect } from 'react';

//箭頭函數(shù)的寫(xiě)法,改變狀態(tài)
const UseEffect = (props) => {
	//創(chuàng)建了一個(gè)叫hook的變量,sethook方法可以改變這個(gè)變量,初始值為‘react hook 是真的好用啊’
	const [ hook, sethook ] = useState('react hook 是真的好用啊');
	const [ name ] = useState('baby張');
	return (
		<header className="UseEffect-header">
			<h4>UseEffect</h4>
			<Child hook={hook} name={name} />
			{/**上面的變量和下面方法也是可以直接使用的 */}
			<button onClick={() => sethook('我改變了react hook 的值' + new Date().getTime())}>改變hook</button>
		</header>
	);
};

const Child = (props) => {
	const [ newhook, setnewhook ] = useState(props.hook);
	//這樣寫(xiě)可以代替以前的componentDidMount,第二個(gè)參數(shù)為空數(shù)組,表示該useEffect只執(zhí)行一次
	useEffect(() => {
		console.log('first componentDidMount');
	}, []);

	//第二個(gè)參數(shù),數(shù)組里是hook,當(dāng)hook變化時(shí),useEffect會(huì)觸發(fā),當(dāng)hook變化時(shí),先銷毀再執(zhí)行第一個(gè)函數(shù)。
	useEffect(
		() => {
			setnewhook(props.hook + '222222222');
			console.log('useEffect');
			return () => {
				console.log('componentWillUnmount ');
			};
		},
		[ props.hook ]
	);

	//useLayoutEffect 強(qiáng)制useeffect的執(zhí)行為同步,并且先執(zhí)行useLayoutEffect內(nèi)部的函數(shù)
	useLayoutEffect(
		() => {
			console.log('useLayoutEffect');
			return () => {
				console.log('useLayoutEffect componentWillUnmount');
			};
		},
		[ props.hook ]
	);

	return (
		<div>
			<p>{props.name}</p>
			{newhook}
		</div>
	);
};

export default UseEffect;

3.useMemo & useCallback

他們都可以用來(lái)優(yōu)化子組件的渲染問(wèn)題,或者監(jiān)聽(tīng)子組件狀態(tài)變化來(lái)處理事件,這一點(diǎn)在以前是很難做到的,因?yàn)閟houldComponentUpdate 里能監(jiān)聽(tīng)到是否變化,但沒(méi)法控制其他的外部方法,只能返回true和false,而componentDidUpdate只能在更新后執(zhí)行,所以想在渲染之前做些事情就不好搞了。
useCallback目前還不能用

import React, { useState, useMemo } from 'react';

const Child = ({ age, name, children }) => {
    //在不用useMemo做處理的時(shí)候,只要父組件狀態(tài)改變了,子組件都會(huì)渲染一次,用了useMemo可以監(jiān)聽(tīng)某個(gè)狀態(tài)name,當(dāng)name變化時(shí)候執(zhí)行useMemo里第一個(gè)函數(shù)
    console.log(age, name, children, '11111111');
	function namechange() {
		console.log(age, name, children, '22222222');
		return name + 'change';
    }
     {/** react 官網(wǎng)雖說(shuō)useCallback與useMemo的功能差不多,但不知道版本問(wèn)題還怎么回是,這個(gè)方法目前還不能用
    const memoizedCallback = useCallback(
        () => {
            console.log('useCallback')
        },
        [name],
      );
    console.log(memoizedCallback,'memoizedCallback')
     */}
    //useMemo有兩個(gè)參數(shù),和useEffect一樣,第一個(gè)參數(shù)是函數(shù),第二個(gè)參數(shù)是個(gè)數(shù)組,用來(lái)監(jiān)聽(tīng)某個(gè)狀態(tài)不變化
	const changedname = useMemo(() => namechange(), [ name ]);
	return (
		<div style={{ border: '1px solid' }}>
			<p>children:{children}</p>
			<p>name:{name}</p>
			<p>changed:{changedname}</p>
			<p>age:{age}</p>
		</div>
	);
};

const UseMemo = () => {
    //useState 設(shè)置名字和年齡,并用2兩個(gè)按鈕改變他們,傳給Child組件
	const [ name, setname ] = useState('baby張'); 
	const [ age, setage ] = useState(18);
	return (
		<div>
			<button
				onClick={() => {
					setname('baby張' + new Date().getTime()); 
				}}
			>
				改名字
			</button>
			<button
				onClick={() => {
					setage('年齡' + new Date().getTime());
				}}
			>
				改年齡
			</button>
			<p>
				UseMemo {name}:{age}
			</p>
			<Child age={age} name={name}>
				{name}的children
			</Child>
		</div>
	);
};

export default UseMemo;

4.useRef

ref跟之前差不多,useRef創(chuàng)建–綁定–使用,三步走,詳細(xì)看代碼以及備注

import React, { useState, useRef } from 'react';

const UseRef = () => {
	//這里useState綁定個(gè)input,關(guān)聯(lián)一個(gè)狀態(tài)name
	const [ name, setname ] = useState('baby張');
	const refvalue = useRef(null);// 先創(chuàng)建一個(gè)空的useRef
	function addRef() {
		refvalue.current.value = name;   //點(diǎn)擊按鈕時(shí)候給這個(gè)ref賦值
		// refvalue.current = name  //這樣寫(xiě)時(shí),即使ref沒(méi)有綁定在dom上,值依然會(huì)存在創(chuàng)建的ref上,并且可以使用它
		console.log(refvalue.current.value);
	}
	return (
		<div>
            <input
                defaultValue={name}
				onChange={(e) => {
					setname(e.target.value);
                }}
			/>
			<button onClick={addRef}>給下面插入名字</button>
			<p>給我個(gè)UseRef名字:</p>
			<input ref={refvalue} />
		</div>
	);
};

export default UseRef;

5.useContext

之前使用過(guò)context的小伙伴一看就懂,useContext的話跟之前的context基本用法差不多,代碼內(nèi)有詳細(xì)注釋說(shuō)明,創(chuàng)建,傳值,使用

import React, { useState, useContext, createContext } from 'react';

const ContextName = createContext();
//這里為了方便寫(xiě)博客,爺爺孫子組件都寫(xiě)在一個(gè)文件里,正常需要在爺爺組件和孫子組件挨個(gè)引入創(chuàng)建的Context

const UseContext = () => {
	//這里useState創(chuàng)建一個(gè)狀態(tài),并按鈕控制變化
	const [ name, setname ] = useState('baby張');
	return (
		<div>
			<h4>UseContext 爺爺</h4>
			<button
				onClick={() => {
					setname('baby張' + new Date().getTime());
				}}
			>
				改變名字
			</button>
			{/**這里跟context用法一樣,需要provider向子組件傳遞value值,value不一定是一個(gè)參數(shù) */}}
			<ContextName.Provider value={{ name: name, age: 18 }}>
				{/**需要用到變量的子組件一定要寫(xiě)在provider中間,才能實(shí)現(xiàn)共享 */}
				<Child />
			</ContextName.Provider>
		</div>
	);
};

const Child = () => {
	//創(chuàng)建一個(gè)兒子組件,里面引入孫子組件
	return (
		<div style={{ border: '1px solid' }}>
			Child 兒子
			<ChildChild />
		</div>
	);
};

const ChildChild = () => {
	//創(chuàng)建孫子組件,接受爺爺組件的狀態(tài),用useContext,獲取到爺爺組件創(chuàng)建的ContextName的value值
	let childname = useContext(ContextName);
	return (
		<div style={{ border: '1px solid' }}>
			ChildChild 孫子
			<p>
				{childname.name}:{childname.age}
			</p>
		</div>
	);
};

export default UseContext;

6.useReducer

這里的usereducer會(huì)返回state和dispatch,通過(guò)context傳遞到子組件,然后直接調(diào)用state或者觸發(fā)reducer,我們常用useReducer 與useContext createContext一起用,模擬reudx的傳值和重新賦值操作。

import React, { useState, useReducer, useContext, createContext } from 'react';

//初始化stroe的類型、初始化值、創(chuàng)建reducer
const ADD_COUNTER = 'ADD_COUNTER';
const initReducer = {
	count: 0
};
//正常的reducer編寫(xiě)
function reducer(state, action) {
	switch (action.type) {
		case ADD_COUNTER:
			return { ...state, count: state.count + 1 };
		default:
			return state;
	}
}

const CountContext = createContext();
//上面這一段,初始化state和reducer創(chuàng)建context,可以單獨(dú)寫(xiě)一個(gè)文件,這里為了方便理解,放一個(gè)文件里寫(xiě)了

const UseReducer = () => {
	const [ name, setname ] = useState('baby張');
	//父組件里使用useReducer,第一個(gè)參數(shù)是reducer函數(shù),第二個(gè)參數(shù)是state,返回的是state和dispash
	const [ state, dispatch ] = useReducer(reducer, initReducer);
	return (
		<div>
			UseReducer
			{/* 在這里通過(guò)context,講reducer和state傳遞給子組件*/}
			<CountContext.Provider value={{ state, dispatch, name, setname }}>
				<Child />
			</CountContext.Provider>
		</div>
	);
};

const Child = () => {
	//跟正常的接受context一樣,接受父組件的值,通過(guò)事件等方式觸發(fā)reducer,實(shí)現(xiàn)redux效果
	const { state, dispatch, name, setname } = useContext(CountContext);
	function handleclick(count) {
		dispatch({ type: ADD_COUNTER, count: 17 });
		setname(count % 2 == 0 ? 'babybrother' : 'baby張');
	}
	return (
		<div>
			<p>
				{name}今年{state.count}歲
			</p>
			<button onClick={() => handleclick(state.count)}>長(zhǎng)大了</button>
		</div>
	);
};

export default UseReducer;

以上是“React Hook是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI