前言
大家好,我是晓羽,文末有我帮助500+名同学完成改造的前端文章!欢迎大家观看~
用法: 能够给useState通过回调函数的形式给useState提供初始参数。
介绍: useState 的参数可以有两种形式:
1. useState(普通的数据) => useState(0) / useState('abc')
2. useState(回调函数) => useState(() => { return 初始值 })
在 useState(回调函数)
中,回调函数的返回值就是状态的初始值, 该回调函数只会触发一次。
const [list, setList] = useState(() => {
return JSON.parse(localStorage.getItem('comments')) || comments
})
该使用哪种形式?
useState(普通的数据)
useState(回调函数)
第一种:
const [list, setList] = useState(
JSON.parse(localStorage.getItem('list')) || arr
)
可以转化为:
这种情况下,只要组件更新,此处的 localStorage 等操作就会重复执行
const initList = JSON.parse(localStorage.getItem('list')) || comments
const [list, setList] = useState(initList)
第二种:
这种方式,因为回调函数只会执行一次,所以,此处的 localStorage 等操作代码只会执行一次
const [list, setList] = useState(() => {
return JSON.parse(localStorage.getItem('comments')) || comments
})
所以在这种情况下,推荐使用第二种方式
用法: 能够在组件卸载的时候,清除注册的事件
介绍: useEffect 的返回值是可选的,可省略。也可以返回一个清理函数,用来执行事件解绑等清理操作。
清理函数的执行时机:
componetWillUnmount
建议:一个 useEffect 只处理一个功能,有多个功能时,使用多次 useEffect
useEffect(() => {
const handleResize = () => {}
window.addEventListener('resize', handleResize)
// 这个返回的函数,会在该组件卸载时来执行
// 因此,可以去执行一些清理操作,比如,解绑 window 的事件、清理定时器 等
return () => window.removeEventListener('resize', handleResize)
})
案例: 能够实现让图片跟随鼠标移动
介绍:
import { useEffect, useState } from 'react'
import img from './1.gif'
export default function Move() {
const [position, setPosition] = useState({
x: 0,
y: 0
})
useEffect(() => {
const move = (e) => {
console.log('开始运动')
setPosition({
x: e.pageX,
y: e.pageY
})
}
document.addEventListener('mousemove', move)
console.log('触发注册事件')
return function () {
document.removeEventListener('mousemove', move)
}
}, [])
return (
)
}
目标: 能够使用自定义hooks实现状态的逻辑复用
内容: 除了使用内置的 Hooks 之外,还可以创建自己的 Hooks(自定义 Hooks)。
useXxx 使用场景: 将组件状态逻辑提取到可重用的函数(自定义 Hooks)中,实现状态逻辑复用。
内置 Hooks 为函数组件赋予了 class 组件的功能;在此之上,自定义 Hooks 针对不同组件实现不同状态逻辑复用。
// 使用hooks实现猫跟着鼠标移动
import { useEffect, useState } from 'react'
export default function useMouse() {
const [position, setPosition] = useState({
x: 0,
y: 0,
})
useEffect(() => {
const move = (e) => {
setPosition({
x: e.pageX,
y: e.pageY,
})
}
document.addEventListener('mousemove', move)
return () => {
document.removeEventListener('mousemove', move)
}
}, [])
return position
}
目的: 能够在函数组件中通过useEffect发送ajax请求
内容: 在组件中,使用 useEffect Hook 发送请求获取数据(side effect):
错误演示:
// 不要给 effect 添加 async
useEffect(async () => {
const res = awiat xxx()
return ()=> {
}
}, [])
正确使用:
useEffect(() => {
async function fetchMyAPI() {
let url = 'http://something/' + productId
let config = {}
const response = await myFetch(url)
}
fetchMyAPI()
}, [productId])
目标: 能够使用useRef操作DOM
内容: 在 React 中进行 DOM 操作时,用来获取 DOM
作用: 返回一个带有 current 属性的可变对象,通过该对象就可以进行 DOM 操作了。
const inputRef = useRef(null)
解释:
/*
1. 使用useRef能够创建一个ref对象, 有current属性 {current: null}
const xxRef = useRef(null)
2. 通过ref属性关联到某个DOM对象上 {current: DOM}
3. 可以通过 xxRef.current访问到对应的DOM
*/
const App = () => {
const inputRef = useRef(null)
const add = () => {
console.log(inputRef.current.value)
}
return (
{' '}
)
}
export default App
目标:实现跨级组件通讯
内容
useContext
是一个 Hook,它可以在函数组件内部使用,以获取 Context 中的值。Context
一起使用,以便在函数组件中方便地访问 Context 数据。useContext 的用法
useContext
接受一个参数,即通过 createContext
创建的 Context 对象。value
属性的值。如果没有对应的 Provider,则返回默认值(如果定义了的话)。useContext 与
的区别
1、
:在 JSX 标签内获取 Context 数据。
2、 useContext
: 在 JavaScript 代码块中获取 Context 数据。
使用场景
Context 的作用
Context 对象包含的两个主要部分
value
属性指定要传递的数据。2.Consumer 组件
render-props
模式在 JSX 中直接获取 Context 中的数据。Consumer 组件行为
value
属性的值。createContext
创建时提供的 defaultValue
。为了更好地理解如何使用 Context
和 useContext
,下面是一个简单的示例:
import React, { createContext, useContext } from 'react';
// 创建 Context
const ThemeContext = createContext();
// Provider 组件
function ThemeProvider({ children }) {
return (
{children}
);
}
// 使用 useContext 的函数组件
function Navbar() {
const theme = useContext(ThemeContext);
return (
The current theme is: {theme}
);
}
// 主组件
function App() {
return (
);
}
export default App;
Context 作用是实现跨组件传递数据,而不必在每个级别手动传递 props,简化组件之间的数据传递过程,那么使用Context 和不使用的区别在哪里呢 ?
不使用Context的情况(传统的Props Drilling)
2. 中间组件 (Intermediate Component)
3.子组件 (Child Component)
这种情况下,数据必须从父组件层层传递到最底层的子组件,即使某些中间组件并不关心这些数据。这被称为“props drilling”。
描述
Parent Component
|
|--- Props
|
+-- Intermediate Component
|
|--- Props
|
+-- Child Component
|
|--- Uses Props
使用Context的情况
2. 中间组件 (Intermediate Component)
3.子组件 (Child Component)
在这种情况下,数据通过Context Provider传递给整个组件树中的所有组件,不需要显式地在每一层都传递props。
Parent Component
|
|--- Context Provider
|
+-- Intermediate Component
|
+-- Child Component
|
|--- useContext to access data
偏爱前端的晓羽:称作2024很强的前端面试场景题,成功帮助532人拿到offer
给你们推荐一篇我帮助500+名同学完成改造的文章,希望大家看完以后都可以领取到心仪的offer哦