上次看了阮一峰老师的文章,写的很通俗易懂,我在这简单给大家梳理一下
我们在开发中常用的就以下四个Hooks。
useState()用于为函数组件引入状态(state)。纯函数不能有状态,所以把状态放在钩子里面。
const [num,setNum] = useState
这一句代码是用白话说就是有个num变量,必须是number类型的(<>尖括号里边的是TYpescript限制类型的写法),初始值为一个数字1,然后setNum就是一个方法,通过一个前缀set就能看出来。setNum(10),通过set了一下,num的值就为10了。
再看一个例子 上面代码中,Button 组件是一个函数,内部使用useState()钩子引入状态。 useState()这个函数接受状态的初始值,作为参数,上例的初始值为按钮的文字。该函数返回一个数组,数组的第一个成员是一个变量(上例是buttonText),指向状态的当前值。第二个成员是一个函数,用来更新状态,约定是set前缀加上状态的变量名(上例是setButtonText)。 如果一个父组件有两个子组件,现在这两个子组件之间需要共享状态,就可以使用useContext 现在有两个组件 Navbar 和 Messages,我们希望它们之间共享状态。 第一步就需要使用React Context API,在组件外部建一个Context。 组件封装代码如下 上面代码中,AppContext.Provider提供了一个 Context 对象,这个对象可以被子组件共享。 在组件 Navbar 和 Messages中,我们可以通过使用 React 本身不提供状态管理功能,通常需要使用外部库。这方面最常用的库是 Redux。 Redux 的核心概念是,组件发出 action 与状态管理器通信。状态管理器收到 action 以后,使用 Reducer 函数算出新的状态,Reducer 函数的形式是 上面是**useReducer()的基本用法,它接受 Reducer 函数和状态的初始值作为参数,返回一个数组。数组的第一个成员是状态的当前值,第二个成员是发送 下面是一个计数器的例子。用于计算状态的 Reducer 函数如下。 组件代码如下。 什么是副作用? 举例来说,我们希望组件加载以后,网页标题(document.title)会随之改变。那么,改变网页标题这个操作,就是组件的副效应,必须通过 上面例子中, 当然 有时候,我们不希望 上面例子中,useEffect()的第二个参数是一个数组,指定了第一个参数(副效应函数)的依赖项( 如果第二个参数是一个空数组,就表明副效应参数没有任何依赖项。因此,副效应函数这时只会在组件加载进入 DOM 后执行一次,后面组件重新渲染,就不会再次执行。这很合理,由于副效应不依赖任何变量,所以那些变量无论怎么变,副效应函数的执行结果都不会改变,所以运行一次就够了。 只要是副效应,都可以使用 注意:使用import React, { useState } from "react";
export default function Button() {
const [buttonText, setButtonText] = useState("Click me, please");
function handleClick() {
return setButtonText("Thanks, been clicked!");
}
return <button onClick={handleClick}>{buttonText}</button>;
}
2、useContext():共享状态钩子
<div className="App">
<Navbar/>
<Messages/>
</div>
const AppContext = React.creactContext({})
<AppContext.Provider value={{
username: 'superawesome'
}}>
<div className="App">
<Navbar/>
<Messages/>
</div>
</AppContext.Provider>
const {username} = useContext(AppContext)
,拿到父组件的username了const Navbar = () => {
const { username } = useContext(AppContext);
return (
<div className="navbar">
<p>AwesomeSite</p>
<p>{username}</p>
</div>
);
}
3、useReducer():action 钩子
(state, action) => newState
。useReducers()
钩子用来引入 Reducer 功能。const [state, dispatch] = useReducer(reducer, initialState);
**action 的dispatch
函数。const myReducer = (state, action) => {
switch(action.type) {
case('countUp'):
return {
...state,
count: state.count + 1
}
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(myReducer, { count: 0 });
return (
<div className="App">
<button onClick={() => dispatch({ type: 'countUp' })}>
+1
</button>
<p>Count: {state.count}</p>
</div>
);
}
4、useEffect():副作用钩子
看到这里,你可能会产生一个疑问:如果纯函数只能进行数据计算,那些不涉及计算的操作(比如生成日志、储存数据、改变应用状态等等)应该写在哪里呢?
函数式编程将那些跟数据计算无关的操作,都称为 “副效应” (side effect) 。如果函数内部直接包含产生副效应的操作,就不再是纯函数了,我们称之为不纯的函数。
纯函数内部只有通过间接的手段(即通过其他函数调用),才能包含副效应。useEffect()
本身是一个函数,由 React 框架提供,在函数组件内部调用即可。useEffect()
来实现。import React, { useEffect } from 'react';
function Welcome(props) {
useEffect(() => {
document.title = '加载完成';
});
return <h1>Hello, {props.name}</h1>;
}
useEffect()
的参数是一个函数,它就是所要完成的副效应(改变网页标题)。组件加载以后,React 就会执行这个函数。
useEffect()
的作用就是指定一个副效应函数,组件每渲染一次,该函数就自动执行一次。组件首次在网页 DOM 加载后,副效应函数也会执行useEffect
也有第二个参数,第二个参数是UseEffect的依赖项。useEffect()
每次渲染都执行,这时可以使用它的第二个参数,使用一个数组指定副效应函数的依赖项,只有依赖项发生变化,才会重新渲染。function Welcome(props) {
useEffect(() => {
document.title = `Hello, ${props.name}`;
}, [props.name]);
return <h1>Hello, {props.name}</h1>;
}
props.name
)。只有该变量发生变化时,副效应函数才会执行。
useEffect()
引入。它的常见用途有下面几种。
useEffect()
时,有一点需要注意。如果有多个副效应,应该调用多个useEffect()
,而不应该合并写在一起。