React-Hooks


title: React-Hooksdate: 2020-06-27 09:13:34

tags: React

class 组件类的缺点

  • 大型业务很难拆分或重构,也很难测试
  • 业务逻辑分散在组件的各个方法中,导致重复逻辑或关联逻辑.
  • 组件类引入了复杂的编程模式,比如render props和高阶组件.

React Hook 的设计目的

加强版函数组件,完全不使用类,就能写出一个全功能组件.

含义为,组件尽量写成纯函数,如果需要外部功能或副作用,就用钩子函数把外部代码”钩”进来.

React 规定,钩子一律使用use前缀命名,便于识别.

常用钩子: useState(),useContext(),useReducer(),useEffect()

useState()状态钩子

用于为函数组件引入状态(state),纯函数不能有状态,所以将状态放入钩子里.

1
2
3
4
5
6
7
8
9
import React, { useState } from 'react';
export default function Button(){
const [buttonText, setButtonText] = useState("Click!")

function handleCilck(){
return setButtonText("thank")
}
return <button onClick={handleClick}>{buttonText}</button>>
}

用户点击后,文字自发生了变化,文字取决于用户是否点击,这就是状态.

Button 组件是一个函数,内部使用useState()引入状态.

useState()函数接收状态的初始值,作为参数,例子中的初始值为按钮的文字,该函数返回一个数组,数组的第一个成员是一个变量(buttonText).

指向状态的当前值.第二个成员是一个函数,用来更新状态.约定是set前缀加上变量名(setButtonText).

useContext()共享状态钩子

如果需要在组件之间共享状态,可以使用useContext().

1
2
3
4
5
6
7
8
const AppContext = React.createContext({})

<AppContext.Provider value={{ username: "super"}}>
<div className="App">
<Navbar />
<Message />
</div>
</AppContext.Provider>

其中,AppContext.Provider提供一个Context对象,这个对象可以被子组件共享.

1
2
3
4
5
6
7
8
9
10
//Navbar.js
const Navbar = () => {
const { username } = useContext(AppContext);
return (
<div className="navbar">
<p>Awesome</p>
<p>{username}</p>
</div>
);
};

其中,useContext()钩子函数用来引入 Context 对象,从中获取username属性.

1
2
3
4
5
6
7
8
9
10
//Message.js
const Message = () => {
const { username } = useContext(AppContext);
return (
<div className="messages">
<p>message for {username}</p>
<p className="message">useContext</p>
</div>
);
};

useReducer(): action 钩子

React 本身不提供状态管理功能,通常使用外部库,如 Redux.

Redux 的核心概念,组件发出 action 与状态管理器通信.状态管理器收到 action 后,使用 Reducer 函数算出新的状态,

Reducer 函数的形式是(state, action)=>newState.

useReducers()用来引入 Reducer 功能.

1
const [state, dispatch] = useReducer(reducer, initialState);

上面是useReducer()的基本用法,它接收 Reducer 函数和状态的初始值作为参数,返回一个数组.数组的第一个成员是状态的当前值,

第二个是发送 action 的dispatch函数.

由于 Hooks 可以提供共享状态和 Reducer 函数,所以这些方面可以取代 redux.但是无提供中间件和时间旅行.

useEffect(): 副作用钩子

useEffect()用来引入具有副作用的操作,如向服务器发送请求数据.

之前放在componentDidMount之中的代码可以放在useEffect()中.

解决了没有生命周期的问题.

用法如下:

1
2
3
useEffect(() => {
//async action
}, [dependencies]);

useEffect()接收两个参数,第一个参数是一个函数,异步操作的代码放在里面.

第二个参数是一个数组,用于给Effect的依赖项,只要这个数组发生变化,useEffect()就会执行.

第二个参数可以省略,这样每次渲染,就会执行useEffect().

第二个参数如果是一个空数组[],就只会在加载时执行一次,数据更新时不执行.

自定义 Hooks