发布于:2021-02-02 10:25:20
0
88
0
React Hooks是React世界的新热点。我正在稳步地写越来越多的书,我想有一个参考的备忘单会很有用,它包含了基本的钩子和复杂的useEffect
。查看官方的Hooks API参考以获取更深入的信息。
useEffect(用于生命周期方法)
useEffect
等,允许您编写自己的副作用,并在需要时触发重新渲染。
但为了更简单,useffect还替代了生命周期方法。让我们谈谈他们。
替换componentDidUpdate+componentDidMount
什么时候开始?每次渲染
有什么问题吗?它不仅仅是一个componentDidUpdate
替代品,它还可以在挂载上运行。所以不是1比1。
重要功能?useffect可以接受第二个参数,您必须跳过该参数。您也可以返回一个函数,我们将在下一节中介绍。
语法:
import { useEffect } from 'react'; useEffect(() => { // whatever runs here will run on each re-render });
替换为componentDidMount+componentWillUnmount
什么时候开始?安装和卸载组件时
有什么问题吗?语法与前面的用例非常接近。好几次我都被它甩了,但只要你看了文件就明白了。如果效果运行多次,请确保传入了第二个参数
重要功能?这是一个只运行一次的效果。mount逻辑放在effect函数的主体中,unmount/cleanup逻辑放在从effect返回的函数中。
语法:
import { useEffect } from 'react'; useEffect(() => { // run mount logic here such as fetching some data return () => { // unmount logic goes here }; }, []); // note the empty array
您可以将mount
或unmount
逻辑保留为空,以便只处理其中一个生命周期替代项。意思是:
保持mount
逻辑为空,以便只有unmount
逻辑运行(仅替换componentWillUnmount
)
不返回任何内容,以便只有mount
逻辑运行(仅替换componentDidMount
)
useEffect的副作用
useEffect
的主要目标是包含您可能想要使用的任何副作用。副作用本质上是你在你的组件中所做的影响整个世界的事情。无论是网络请求、设置文档标题,还是其他什么。
必要时运行
什么时候开始?当组件重新呈现时,useEffect
将检查依赖项。如果依赖项值更改,useffect将运行该效果
有什么问题吗?React做了一个浅显的比较。如果您使用一个对象或一个数组,您的反应会认为没有改变。
重要特性useEffect在情况不变时跳过运行效果。实际上,您不必在效果中使用依赖项值。可以作为依赖项传入prop值。
语法:
import { useEffect } from 'react'; function SomeComponent(props) { useEffect(() => { // logic runs only when dependency variables changed }, [arrOfDependency, values, props.id]); // array of values to check if they've changed }
潜在用例
由于钩子更难解释,我想提供一个用例列表
当道具更改以获取新数据时运行副作用(如获取)
仅当计算值更改时运行资源密集型计算
当值更新时更新页面(如文档标题)
useState
状态可能是人们从无状态(功能)组件切换到类组件的原因。useState
允许我们拥有无类的有状态组件。
它返回什么?当前状态和用于设置状态的函数
有什么问题吗?状态设置函数将用新状态替换以前的状态,而不是像类状态那样合并它们。在设置状态之前,您需要自己合并对象。
重要功能您可以在组件中使用任意多个useState
挂钩。将任何值传递给useState
将创建初始状态。这也是一种惯例,不调用变量state
和setState
,而是使用上下文名称(例如user
和setUser
)。接受状态的任何值,它不必是对象。
语法:
import { useState } from 'react'; // setup const defaultValue = { name: "Antonin" }; const [state, setState] = useState(defaultValue); // scenario 1 usage // resulting state only contains key `user` with value 'antjanus' setState({ user: 'antjanus' }); // scenario 2 usage // resulting state contains key `name` with value 'A. Januska' setState({ name: 'A. Januska' }); // scenario 3 usage // resulting state is a merger between `{ name: 'A. Januska' }` and `{ user: 'antjanus'}` setState({ ...state, user: 'antjanus'});
useReducer
useReducer
是useState
的另一种选择,如果您以前使用过Redux,这看起来会很熟悉。
有什么争论?它返回什么?useReducer
采用reducer
函数和initialState
。它返回当前的state
和adispatcher
(听起来很熟悉?)
它是如何运行的?在状态更改时,dispatch
具有类型和数据有效负载的对象(有关更多信息,请参阅flux标准操作)。传递给useReducer的reducer
将接收当前状态和已调度对象。它返回新状态。
有什么问题吗?这是一个更复杂的工作流,但它的工作原理与您使用Redux时所期望的一样。
重要功能减速机每次调度都会运行。它可以访问以前的状态。useReducer
还包括可用于创建初始状态的第三个参数。
语法
import { useReducer } from 'react'; function reducer(currentState, action) { switch(action.type) { // handle each action type and how it affects the current state here } } function SomeComponent() { const [state, dispatch] = useReducer(reducer, initialState); dispatch({ type: 'ADD', payload: data }); // { type: 'ADD', payload: data } gets passed into the `reducer` as the `action` argument while `state` gets passed in as the `currentState` argument }
建立自己的钩子
关于构建自己的钩子的简短说明。这就像使用现有的钩子并将它们组合在一个以use
开头的函数中一样简单。下面是一个useUser
钩子的快速示例。
有什么要求?函数以关键字use
开始。例如useUser
或useSomethingElse
。
重要特性:您可以调用自定义钩子中的任何钩子,并按预期工作。
语法:
import { useEffect } from 'react'; function useUser(userId) { let [user, setUser] = useState(null); useEffect(() => { fetch(`/api/user/${userId}`) .then(data => data.toJSON()) .then(data => setUser(data)); }, [userId]); return user; } function SomeComponent(props) { const user = useUser(props.id); }
剩下的呢?
您还可以使用其他挂钩,如useMemo
、useCallback
等等。我想说那些是更高级的钩子,如果你了解基本的钩子,那就去看看官方文档吧。
我也知道其中有很多高级用法示例(比如将useReducer的dispatch
传递到几个级别)。
如果您发现一些不正确的或一些额外的有用的信息是不包括在内,让我知道!我会把它包括在内!
作者介绍