React 16.8新特性?HOOKS你一定要知道!(非常详细)

news/2025/2/23 6:10:38/

Facebook团队对社区上的MVC框架都不太满意的情况下,开发了一套开源的前端框架react,于2013年发布第一个版本。

react最开始倡导函数式编程,使用function以及内部方法React.creactClass创建组件,之后在ES6推出之后,使用类组件Class构建包含生命周期的组件。 

React 16.8是一个比较重要的版本,它主要新增了Hooks这一特性,改变了React中组件的写法方式。

Hooks:

Hooks是React 16.8中最重要的新增特性。Hooks本质上就是一类特殊的函数,它们可以为你的函数型组件(function component)注入一些特殊的功能,让您在不编写类的情况下使用 state(状态) 和其他 React 特性。使用Hooks,可以更方便地使用状态和副作用,同时也可以避免类组件中的一些问题。

React Hooks的出现让函数组件和类组件之间的差距变得更小,使得我们在开发React应用时更加灵活、简便。同时,React Hooks还可以帮助我们更好地组织和复用组件逻辑。

为什么要使用 React Hooks

  • 状态逻辑难以复用: 业务变得复杂之后,组件之间共享状态变得频繁,组件复用和状态逻辑管理就变得十分复杂。使用redux也会加大项目的复杂度和体积。
  • 组成复杂难以维护: 复杂的组件中有各种难以管理的状态和副作用,在同一个生命周期中你可能会因为不同情况写出各种不相关的逻辑,但实际上我们通常希望一个函数只做一件事情。
  • 类的this指向性问题: 我们用class来创建react组件时,为了保证this的指向正确,我们要经常写这样的代码:const that = this,或者是this.handleClick = this.handleClick.bind(this)>;一旦this使用错误,各种bug就随之而来。

为了解决这些麻烦,hooks 允许我们使用简单的特殊函数实现class的各种功能。

官方Hooks 

一:useContext:

useContext是React Hooks中的一种,它可以让我们在函数组件中使用Context。

Context是React中一种组件间通信的方式,可以让我们避免通过props层层传递数据,从而让组件间的通信更加简单和直接。使用useContext可以让我们更方便地使用Context,避免了类组件中使用Context时需要使用this.context的麻烦。

使用useContext需要传入一个Context对象,该对象可以通过React.createContext创建。一般来说,在应用中我们会提供一个Context,然后在需要使用该Context的组件中使用useContext获取对应的值。例如:


import React, { useContext } from 'react';
const MyContext = React.createContext({ name: 'default' });
function MyComponent() {const { name } = useContext(MyContext);return <div>{name}</div>;
}
function App() {return (<MyContext.Provider value={{ name: 'John' }}><MyComponent /></MyContext.Provider>);
}

在上面的例子中,我们创建了一个名为MyContext的Context,并在App组件中提供了一个值{name: 'John'}。在MyComponent组件中,我们可以使用useContext(MyContext)获取到该值,并将其渲染到页面上。
使用useContext可以大大简化组件间通信的代码,同时也可以让我们更好地组织和复用组件逻辑。 

二:useReducer:

useReducer是React Hooks中的一种,它可以让我们在函数组件中使用Reducer。

Reducer是一种状态管理模式,常用于复杂应用的状态管理。使用Reducer可以让我们更好地组织和管理组件的状态。

使用useReducer需要传入一个Reducer函数和一个初始状态。Reducer函数接收当前状态和一个action对象,返回一个新的状态。当我们需要更新状态时,可以使用dispatch函数触发对应的action,从而更新状态。例如:

import React, { useReducer } from 'react';
function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:throw new Error();}
}
function Counter({ initialCount }) {const [state, dispatch] = useReducer(reducer, { count: initialCount });return (<>Count: {state.count}<button onClick={() => dispatch({ type: 'increment' })}>+</button><button onClick={() => dispatch({ type: 'decrement' })}>-</button></>);
}
function App() {return <Counter initialCount={0} />;
}

在上面的例子中,我们创建了一个名为reducer的Reducer函数,它接收当前状态state和action对象,返回一个新的状态。我们还创建了一个名为Counter的组件,该组件使用useReducer来管理状态,并通过dispatch函数触发对应的action来更新状态。在App组件中,我们渲染了Counter组件,并传入了一个初始状态{ count: 0 }。

使用useReducer可以让我们更好地管理组件的状态,同时也可以更好地组织和复用组件逻辑。它和useState一样,都可以用于管理组件的状态,但是在复杂的场景下,useReducer可以更好地处理状态的变化。 

三:useEffect:

useEffect是React Hooks中的一种,它可以让我们在函数组件中处理副作用。

副作用指的是那些不属于组件渲染输出的,但是对组件渲染输出结果产生影响的操作,例如向服务器发送网络请求、访问浏览器缓存等操作

使用useEffect可以让我们更方便地处理这些副作用。
使用useEffect需要传入一个函数和一个依赖数组。该函数可以执行一些副作用操作,例如向服务器发送网络请求、访问浏览器缓存等等。当组件渲染到页面上时,useEffect会自动执行该函数。同时,如果依赖数组中的任何一个值发生了改变,useEffect也会重新执行该函数。如果依赖数组为空,useEffect只会在组件挂载和卸载时执行一次。例如:

import React, { useState, useEffect } from 'react';
function Counter() {const [count, setCount] = useState(0);useEffect(() => {document.title = `You clicked ${count} times`;}, [count]);return (<div><p>You clicked {count} times</p ><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

在上面的例子中,我们创建了一个名为Counter的组件,并使用useState来管理状态。我们还使用useEffect来更新页面标题,当count的值发生改变时,useEffect会重新执行,从而更新页面标题。在Counter组件中,我们渲染了一个计数器和一个按钮,点击按钮可以让计数器递增。
使用useEffect可以让我们更方便地处理副作用,它和类组件中的componentDidMount、componentDidUpdate和componentWillUnmount方法类似,但是使用起来更加简单方便。同时,使用useEffect也可以让我们更好地遵循React的基本原则,即“将组件渲染输出和副作用分开处理”。

四:useCallback:

useCallback是React Hooks中的一种,它可以让我们更好地处理函数的性能问题。

在React中,每次状态改变或props改变时,函数组件会重新渲染,如果函数组件中的函数没有被优化,每次重新渲染都会导致函数的重新创建和重新分配内存,造成性能浪费。

使用useCallback可以让我们缓存函数,避免不必要的重新创建和分配内存。
使用useCallback需要传入一个函数和一个依赖数组。该函数会被缓存,只有依赖数组中的值发生改变时,才会重新创建该函数。例如:

import React, { useState, useCallback } from 'react';
function Counter() {const [count1, setCount1] = useState(0);const [count2, setCount2] = useState(0);const handleClick = useCallback(() => {setCount1(count1 + 1);}, [count1]);return (<div><p>Count1: {count1}</p ><p>Count2: {count2}</p ><button onClick={handleClick}>Click me</button></div>);
}

在上面的例子中,我们创建了一个名为handleClick的回调函数,并使用useCallback缓存该函数。当count1的值发生改变时,该函数才会重新创建。在Counter组件中,我们渲染了两个计数器和一个按钮,点击按钮可以让count1递增。
使用useCallback可以让我们更好地处理函数的性能问题,避免不必要的重新创建和分配内存。它适用于那些需要频繁传递给子组件的回调函数,例如在列表中渲染子项时,需要给每个子项传递一个回调函数来处理点击事件。

五:useRef:

useRef是React Hooks中的一种,它可以在函数组件中使用ref。

ref通常用于获取组件或DOM节点的引用,或者用于在组件之间共享数据。使用useRef可以让我们更方便地在函数组件中使用ref。

使用useRef需要调用React.useRef()函数,并将其赋值给某个变量。该变量的current属性可以用于存储和访问ref的值。例如:

import React, { useRef } from 'react';
function TextInputWithFocusButton(props) {const inputEl = useRef(null);const onButtonClick = () => {inputEl.current.focus();};return (<div><input ref={inputEl} type="text" /><button onClick={onButtonClick}>Focus the input</button></div>);
}

在上面的例子中,我们创建了一个名为inputEl的ref,并将其赋值给input元素的ref属性。我们还创建了一个名为onButtonClick的函数,该函数可以通过inputEl.current.focus()来让input元素获得焦点。在TextInputWithFocusButton组件中,我们渲染了一个input元素和一个按钮,点击该按钮可以让input元素获得焦点。
使用useRef可以让我们更方便地在函数组件中使用ref,避免了在类组件中使用ref时需要使用this.refs的麻烦。除了获取DOM节点的引用,useRef还可以用于在组件之间共享数据,因为它可以在组件之间保持数据的引用。 

六:useMemo:

useMemo是React Hooks中的一种,它可以让我们更好地处理计算密集型的操作,避免不必要的重新计算。

在React中,每次状态改变或props改变时,函数组件会重新渲染,如果组件中存在一些计算密集型的操作,每次重新渲染都会导致这些操作的重新计算,造成性能浪费。使用useMemo可以让我们缓存计算结果,避免不必要的重新计算。
使用useMemo需要传入一个计算函数和一个依赖数组。该计算函数会被缓存,只有依赖数组中的值发生改变时,才会重新计算。例如:

import React, { useState, useMemo } from 'react';
function Counter() {const [count1, setCount1] = useState(0);const [count2, setCount2] = useState(0);const result = useMemo(() => {return count1 * count2;}, [count1, count2]);return (<div><p>Result: {result}</p ><button onClick={() => setCount1(count1 + 1)}>Increment Count1</button><button onClick={() => setCount2(count2 + 1)}>Increment Count2</button></div>);
}

在上面的例子中,我们创建了一个名为result的变量,并使用useMemo缓存该变量。当count1或count2的值发生改变时,该变量才会重新计算。在Counter组件中,我们渲染了一个结果和两个按钮,点击按钮可以让count1或count2递增。
使用useMemo可以让我们更好地处理计算密集型的操作,避免不必要的重新计算。它适用于那些需要进行复杂计算或者需要大量数据处理的操作,例如在列表中渲染子项时,需要对子项进行复杂计算或者大量数据处理。

七:useLayoutEffect: 

useLayoutEffect是React Hooks中的一种,它和useEffect很类似,但它在视图更新之前同步执行,可以用来进行DOM操作或者进行一些需要同步执行的操作。

在React中,每次状态改变或props改变时,组件会重新渲染,如果组件中存在一些需要同步执行的操作,例如DOM操作,使用useLayoutEffect可以确保这些操作在视图更新之前执行。
使用useLayoutEffect需要传入一个副作用函数和一个依赖数组。该副作用函数会在DOM更新之前同步执行,可以进行DOM操作或者进行一些需要同步执行的操作,例如使用第三方库操作DOM或者进行一些测量操作。例如:

import React, { useState, useLayoutEffect } from 'react';
function Counter() {const [count, setCount] = useState(0);useLayoutEffect(() => {const title = document.querySelector('title');title.innerText = `Count: ${count}`;}, [count]);return (<div><p>Count: {count}</p ><button onClick={() => setCount(count + 1)}>Increment Count</button></div>);
}

在上面的例子中,我们使用useLayoutEffect在DOM更新之前同步修改了页面的title,使其显示当前的count值。在Counter组件中,我们渲染了一个计数器和一个按钮,点击按钮可以让count递增。
使用useLayoutEffect可以确保一些操作在DOM更新之前同步执行,适用于那些需要同步执行的操作,例如DOM操作或者进行一些测量操作。但由于它在视图更新之前同步执行,所以需要注意性能问题,确保操作的执行时间不会太长,避免阻塞主线程。 

八:useImperativeHandle: 

 useImperativeHandle是React Hooks中的一种,它可以让我们在函数组件中访问子组件的实例方法或属性。

在React中,父组件可以通过ref访问子组件的实例,但是在函数组件中,我们无法通过ref访问子组件的实例。使用useImperativeHandle可以让我们在函数组件中定义子组件的实例方法或属性,并通过ref访问这些实例方法或属性。
使用useImperativeHandle需要传入一个ref对象和一个副作用函数。该副作用函数会返回一个对象,该对象中包含了子组件的实例方法或属性。例如:

import React, { useRef, useImperativeHandle } from 'react';
const Child = React.forwardRef((props, ref) => {const inputRef = useRef(null);useImperativeHandle(ref, () => ({focusInput: () => {inputRef.current.focus();}}));return (<div><input type="text" ref={inputRef} /></div>);
});
function Parent() {const childRef = useRef(null);const handleClick = () => {childRef.current.focusInput();};return (<div><Child ref={childRef} /><button onClick={handleClick}>Focus Input</button></div>);
}

在上面的例子中,我们定义了一个名为Child的子组件,并通过forwardRef向外暴露了一个ref。在Child组件中,我们使用useImperativeHandle定义了一个名为focusInput的实例方法,并将该方法作为对象返回。在Parent组件中,我们使用childRef访问了Child组件的实例,并在按钮的点击事件中调用了focusInput方法,使得input元素获取了焦点。
使用useImperativeHandle可以让我们在函数组件中访问子组件的实例方法或属性,但同时也需要注意一些性能问题,确保不会滥用该功能。

九:useReducer: 

useReducer是React Hooks中的一种,它可以让我们使用类似Redux的状态管理方式,将组件的状态转移到Reducer中,从而更好地管理组件的状态。

在React中,每次状态改变或props改变时,函数组件会重新渲染,如果组件中存在一些复杂的状态逻辑,使用useReducer可以更好地管理这些状态逻辑,使得代码更加清晰易懂。
使用useReducer需要传入一个reducer函数和一个初始状态。该reducer函数接受当前状态和一个action对象作为参数,并返回一个新的状态。action对象通常包含一个type属性和一些其他属性,用来描述状态的变化。例如:

import React, { useReducer } from 'react';
function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:throw new Error();}
}
function Counter() {const [state, dispatch] = useReducer(reducer, { count: 0 });return (<div><p>Count: {state.count}</p ><button onClick={() => dispatch({ type: 'increment' })}>Increment Count</button><button onClick={() => dispatch({ type: 'decrement' })}>Decrement Count</button></div>);
}

在上面的例子中,我们创建了一个名为reducer的函数,用来描述计数器的状态变化。在Counter组件中,我们使用useReducer将组件的状态转移到reducer中,并使用dispatch函数来触发状态的变化。我们渲染了一个计数器和两个按钮,点击按钮可以让计数器的值递增或递减。
使用useReducer可以让我们更好地管理组件的状态,特别是那些复杂的状态逻辑,使得代码更加清晰易懂。它适用于那些需要进行状态管理的组件,例如表单、列表等。 

自定义Hooks

  • 自定义Hooks:可以封装状态,能够更好的实现状态共享。
  • 自定义hooks可以说成是一种约定而不是功能。
  • 当一个函数以use开头并且在函数内部调用其他hooks,那么这个函数就可以成为自定义hooks。

自定义Hooks是React中的一种编程模式,它可以让我们把组件中的逻辑抽象出来,从而使得我们可以在多个组件中复用该逻辑。自定义Hooks通常以use开头,并使用其他Hooks或JavaScript函数来实现某些功能。

例如,我们可以创建一个名为useFetch的自定义Hook,用来发送网络请求并返回数据。该Hook接受一个URL作为参数,并返回一个包含数据、错误和是否正在加载的状态。

该Hook使用了useEffect和useState等React Hooks来实现异步数据的获取和状态管理。

例如:

import { useState, useEffect } from 'react';
function useFetch(url) {const [data, setData] = useState(null);const [error, setError] = useState(null);const [isLoading, setIsLoading] = useState(true);useEffect(() => {async function fetchData() {try {const response = await fetch(url);const json = await response.json();setData(json);} catch (error) {setError(error);} finally {setIsLoading(false);}}fetchData();}, [url]);return { data, error, isLoading };
}

在上面的例子中,我们创建了一个名为useFetch的自定义Hook,用来发送网络请求并返回数据。该Hook使用了useState和useEffect等React Hooks来管理数据、错误和加载状态,并在组件中使用该Hook来获取数据。

例如:

import React from 'react';
import useFetch from './useFetch';
function Post({ id }) {const { data, error, isLoading } = useFetch(`https://jsonplaceholder.typicode.com/posts/${id}`);if (isLoading) {return <div>Loading...</div>;}if (error) {return <div>Error: {error.message}</div>;}return (<div><h2>{data.title}</h2><p>{data.body}</p ></div>);
}

在上面的例子中,我们使用了useFetch自定义Hook来获取单个博客文章的数据,并在组件中根据加载状态和错误状态进行渲染。该自定义Hook可以在其他组件中复用,从而实现了逻辑的复用和代码的重用。
自定义Hooks可以让我们把组件中的逻辑抽象出来,从而实现逻辑的复用和代码的重用。它适用于那些需要在多个组件中复用的逻辑或功能,例如网络请求、表单验证等。

 


http://www.ppmy.cn/news/140786.html

相关文章

japanhr日语小工具 日文汉字转平假名-japankana

japanhr 很好&#xff0c;但是不能在windows 10 上使用&#xff0c;利用业余时间依赖Electron做了下面这个软件&#xff0c;没有病毒&#xff0c;有免安装版和多个系统版本。推荐给大家 我已经开放了源代码&#xff1a;https://github.com/styunan/japankana 官网&#xff1a;…

百度网盘下载器

说明&#xff1a;百度云不开会员真的是龟速&#xff0c;就在大佬的博客上找了好多百度网盘的下载器&#xff0c;这里罗列出来几个&#xff0c;可以去大佬博客上下载。 Speedpan&#xff1a;百度网盘满速下载工具&#xff0c;无需登录&#xff0c;也可直接下载BT种子 Speedpan …

自动批量日文翻译工具,免费日文等小语种翻译互译工具

日文翻译工具具有日文、俄语、韩语、德语等多国小语种翻译&#xff0c;支持日文整篇文章翻译成中文等多种语种&#xff0c;长篇文章翻译后保留原文格式段落&#xff0c;并通过批量内容编辑处理&#xff0c;实现翻译后的文章敏感词删除、插图图片和同义词替换实现本地化翻译。 日…

中日翻译在线翻译如何利用日语翻译软件完成

中日翻译在线翻译如何利用日语翻译软件完成&#xff1f;对于喜欢看日漫的朋友们来说&#xff0c;肯定都有一颗去日本旅游的心&#xff0c;但是去日本旅游首先我们要解决中日语翻译的问题。今天小编将要分享给大家一个方法&#xff0c;帮助大家快速完成中日语翻译。 1&#xf…

如何将日语在线翻译成中文

如何将日语在线翻译成中文&#xff1f;日本的动漫产业非常发达&#xff0c;作为从小看日漫长大的我们&#xff0c;谁都想学习几句日语或者将我们的口头禅翻译为日语。所以今天小编将要教大家一个方法&#xff0c;帮助小伙伴们快速将日语在线翻译为中文&#xff0c;小伙伴们要不…

如何利用日语翻译软件快速进行日语翻译

如何利用日语翻译软件快速进行日语翻译&#xff1f;日本的文化中很大一部分都传承于我国唐朝&#xff0c;所以许多人想去日本旅游&#xff0c;感受本土文化在异国他乡所流传下的魅力。但是许多人不会日语该怎么办呢&#xff1f;今天小编就教大家一个快速进行日语翻译的方法&…

多种文字翻译软件-翻译常用软件

整篇文档翻译软件 整篇文档翻译软件是一种实现全文翻译的自动翻译工具&#xff0c;它能够快速、准确地将整篇文档的内容翻译成目标语言。与单词、句子翻译不同&#xff0c;整篇文档翻译软件不仅需要具备准确的语言识别和翻译技术&#xff0c;还需要考虑上下文语境和文档格式等多…