React中10種Hook的使用介紹
React Hook是什么?
React官網是這么介紹的: Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。
完全可選的 你無需重寫任何已有代碼就可以在一些組件中嘗試 Hook。但是如果你不想,你不必現在就去學習或使用 Hook。
100% 向后兼容的 Hook 不包含任何破壞性改動。
現在可用 Hook 已發(fā)布于 v16.8.0。
沒有計劃從 React 中移除 class 你可以在本頁底部的章節(jié)讀到更多關于 Hook 的漸進策略。
Hook 不會影響你對 React 概念的理解 恰恰相反,Hook 為已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命周期。稍后我們將看到,Hook 還提供了一種更強大的方式來組合他們。
如果對react還不夠了解建議先看下react官方文檔,寫寫demo再來看文章,因為有的react基礎的東西我就一筆帶過不細說。
react 官方文檔 https://zh-hans.reactjs.org/docs/hooks-state.html
React目前提供的Hook
| hook | 用途 |
|---|---|
| useState | 設置和改變state,代替原來的state和setState |
| useEffect | 代替原來的生命周期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合并版 |
| useLayoutEffect | 與 useEffect 作用相同,但它會同步調用 effect |
| useMemo | 控制組件更新條件,可根據狀態(tài)變化控制方法執(zhí)行,優(yōu)化傳值 |
| useCallback | useMemo優(yōu)化傳值,usecallback優(yōu)化傳的方法,是否更新 |
| useRef | 跟以前的ref,一樣,只是更簡潔了 |
| useContext | 上下文爺孫及更深組件傳值 |
| useReducer | 代替原來redux里的reducer,配合useContext一起使用 |
| useDebugValue | 在 React 開發(fā)者工具中顯示自定義 hook 的標簽,調試使用。 |
| useImperativeHandle | 可以讓你在使用 ref 時自定義暴露給父組件的實例值。 |
1.useState
import React from 'react';
import './App.css';
//通常的class寫法,改變狀態(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}
//函數式寫法,改變狀態(tài)
function App() {
//創(chuàng)建了一個叫hook的變量,sethook方法可以改變這個變量,初始值為‘react hook 是真的好用啊'
const [hook, sethook] = useState("react hook 是真的好用啊");
return (
<header className="App-header">
{hook}{/**這里的變量和方法也是可以直接使用的 */}
<button onClick={() => sethook("我改變了react hook 的值")}>
改變hook
</button>
</header>
);
}
export {App}
//箭頭函數的函數寫法,改變狀態(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的對比使用,一個小的demo結構更清晰,代碼更簡潔,更像寫js代碼,運用到項目中,那豈不是美滋滋。
2.useEffect & useLayoutEffect
useEffect代替原來的生命周期,componentDidMount,componentDidUpdate 和 componentWillUnmount 的合并版
useEffect( ()=>{ return ()=>{ } } , [ ])
- 第一個參數,是函數,默認第一次渲染和更新時都會觸發(fā),默認自帶一個return ,return一個函數表示可以再銷毀之前可以處理些事情
- 第二個參數,數組【】,空的時候表示只執(zhí)行一次,更新時不觸發(fā),里面的參數是什么,當參數變化時才會執(zhí)行useEffect
- useEffect可以多次使用,按照先后順序執(zhí)行
- useLayoutEffect 強制useeffect的執(zhí)行為同步,并且先執(zhí)行useLayoutEffect內部的函數
import React, { useState, useEffect, useLayoutEffect } from 'react';
//箭頭函數的寫法,改變狀態(tài)
const UseEffect = (props) => {
//創(chuàng)建了一個叫hook的變量,sethook方法可以改變這個變量,初始值為‘react hook 是真的好用啊'
const [ hook, sethook ] = useState('react hook 是真的好用啊');
const [ name ] = useState('baby張');
return (
<header className="UseEffect-header">
<h3>UseEffect</h3>
<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);
//這樣寫可以代替以前的componentDidMount,第二個參數為空數組,表示該useEffect只執(zhí)行一次
useEffect(() => {
console.log('first componentDidMount');
}, []);
//第二個參數,數組里是hook,當hook變化時,useEffect會觸發(fā),當hook變化時,先銷毀再執(zhí)行第一個函數。
useEffect(
() => {
setnewhook(props.hook + '222222222');
console.log('useEffect');
return () => {
console.log('componentWillUnmount ');
};
},
[ props.hook ]
);
//useLayoutEffect 強制useeffect的執(zhí)行為同步,并且先執(zhí)行useLayoutEffect內部的函數
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
他們都可以用來優(yōu)化子組件的渲染問題,或者監(jiān)聽子組件狀態(tài)變化來處理事件,這一點在以前是很難做到的,因為shouldComponentUpdate 里能監(jiān)聽到是否變化,但沒法控制其他的外部方法,只能返回true和false,而componentDidUpdate只能在更新后執(zhí)行,所以想在渲染之前做些事情就不好搞了。
useCallback目前還不能用
import React, { useState, useMemo } from 'react';
const Child = ({ age, name, children }) => {
//在不用useMemo做處理的時候,只要父組件狀態(tài)改變了,子組件都會渲染一次,用了useMemo可以監(jiān)聽某個狀態(tài)name,當name變化時候執(zhí)行useMemo里第一個函數
console.log(age, name, children, '11111111');
function namechange() {
console.log(age, name, children, '22222222');
return name + 'change';
}
{/** react 官網雖說useCallback與useMemo的功能差不多,但不知道版本問題還怎么回是,這個方法目前還不能用
const memoizedCallback = useCallback(
() => {
console.log('useCallback')
},
[name],
);
console.log(memoizedCallback,'memoizedCallback')
*/}
//useMemo有兩個參數,和useEffect一樣,第一個參數是函數,第二個參數是個數組,用來監(jiān)聽某個狀態(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 設置名字和年齡,并用2兩個按鈕改變他們,傳給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)建–綁定–使用,三步走,詳細看代碼以及備注
import React, { useState, useRef } from 'react';
const UseRef = () => {
//這里useState綁定個input,關聯一個狀態(tài)name
const [ name, setname ] = useState('baby張');
const refvalue = useRef(null);// 先創(chuàng)建一個空的useRef
function addRef() {
refvalue.current.value = name; //點擊按鈕時候給這個ref賦值
// refvalue.current = name //這樣寫時,即使ref沒有綁定在dom上,值依然會存在創(chuàng)建的ref上,并且可以使用它
console.log(refvalue.current.value);
}
return (
<div>
<input
defaultValue={name}
onChange={(e) => {
setname(e.target.value);
}}
/>
<button onClick={addRef}>給下面插入名字</button>
<p>給我個UseRef名字:</p>
<input ref={refvalue} />
</div>
);
};
export default UseRef;
5.useContext
之前使用過context的小伙伴一看就懂,useContext的話跟之前的context基本用法差不多,代碼內有詳細注釋說明,創(chuàng)建,傳值,使用
import React, { useState, useContext, createContext } from 'react';
const ContextName = createContext();
//這里為了方便寫博客,爺爺孫子組件都寫在一個文件里,正常需要在爺爺組件和孫子組件挨個引入創(chuàng)建的Context
const UseContext = () => {
//這里useState創(chuàng)建一個狀態(tài),并按鈕控制變化
const [ name, setname ] = useState('baby張');
return (
<div>
<h3>UseContext 爺爺</h3>
<button
onClick={() => {
setname('baby張' + new Date().getTime());
}}
>
改變名字
</button>
{/**這里跟context用法一樣,需要provider向子組件傳遞value值,value不一定是一個參數 */}}
<ContextName.Provider value={{ name: name, age: 18 }}>
{/**需要用到變量的子組件一定要寫在provider中間,才能實現共享 */}
<Child />
</ContextName.Provider>
</div>
);
};
const Child = () => {
//創(chuàng)建一個兒子組件,里面引入孫子組件
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會返回state和dispatch,通過context傳遞到子組件,然后直接調用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編寫
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,可以單獨寫一個文件,這里為了方便理解,放一個文件里寫了
const UseReducer = () => {
const [ name, setname ] = useState('baby張');
//父組件里使用useReducer,第一個參數是reducer函數,第二個參數是state,返回的是state和dispash
const [ state, dispatch ] = useReducer(reducer, initReducer);
return (
<div>
UseReducer
{/* 在這里通過context,講reducer和state傳遞給子組件*/}
<CountContext.Provider value={{ state, dispatch, name, setname }}>
<Child />
</CountContext.Provider>
</div>
);
};
const Child = () => {
//跟正常的接受context一樣,接受父組件的值,通過事件等方式觸發(fā)reducer,實現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)}>長大了</button>
</div>
);
};
export default UseReducer;
附上github地址 10個hook demo 點一點star,謝謝咯!
github地址:https://github.com/babybrotherzb/React-Hook
到此這篇關于React中10種Hook的使用介紹的文章就介紹到這了,更多相關React Hook內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
React?Native實現Toast輕提示和loading效果
這篇文章主要介紹了React Native實現Toast輕提示和loading效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-09-09
React基礎-JSX的本質-虛擬DOM的創(chuàng)建過程實例分析
這篇文章主要介紹了React基礎-JSX的本質-虛擬DOM的創(chuàng)建過程,結合具體實例形式分析了虛擬dom的基本原理與實現方法,需要的朋友可以參考下2023-05-05
React immer與Redux Toolkit使用教程詳解
這篇文章主要介紹了React中immer與Redux Toolkit的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-10-10

