react18 之 04 函数组件 使用hook定义变量,修改数据等
- 使用规则
- 1:Hook不能在类组件中使用,只能在函数组件以及自定义Hook中使用
- 2:只能在函数组件的最外层调用Hook,不能在循环、判断或子函数中调用Hook
react 函数组件 01:使用useState hook ( 类似state存储数据。eg:点击按钮,使得count自动+1)
- 使用useState,可以在函数组件之中使用 state
import React, { useState } from 'react';
export default function UseState() {
const [count, setCount] = useState(0)
function countAdd() {
let res = count + 1
setCount(res)
}
return (
<div className='content'>
count - { count } <button onClick={countAdd}>count++</button>
</div>
)
}
react 函数组件 02:使用useEffect hook (组件的挂载、组件的更新、组件的卸载为一体)
- React官方文档中,把数据获取、操作DOM、订阅数据、调用浏览器API等操作,称为副作用
- 这个hook函数类似于(componentDidMount、componentDidUpdate 和 componentWillUnmount)也就是集成了组件的挂载、组件的更新、组件的卸载为一体
- 这个hook函数,分为组件挂载时执行,组件视图更新执行,组件监测某个值或者某些值更新后执行
- 1:组件挂载时执行
useEffect( () => {}, [] )
就是后面传递了 [] 限制的 - 1:组件挂载与卸载时执行
useEffect( () => { return ()=> {} }, [] )
就是里面有 return ()=> {}
便是组件卸载的时候执行。可以清理副作用啥的 - 2:组件视图更新执行
useEffect( () => {} )
- 3:组件监测某个值或者某些值更新后执行
useEffect( () => {}, [timer] )
就是后面传递了 [timer] 限制timer变化时才执行
useEffect 实现 组件挂载修改title和初始化时候调用接口拿数据
import React, { useEffect, useState } from 'react';
export default function UseEffect() {
useEffect(() => {
console.log('useEffect每次渲染后执行')
})
useEffect(() => {
console.log('useEffect-组件挂载后执行')
document.title = '我是UseEffect'
}, [])
return (
<div className='content'>
UseEffect
</div>
)
}
useEffect 实现 组件卸载时 清除定时器
- useEffect里面的 return ()=>{} 是组件卸载的时候执行
app.jsx
import React, { Component } from 'react';
import UseState from './useState';
export default class app extends Component {
state = {
isShowUseEffect: true
}
componentDidMount() {}
closeUseEffect = () => {
console.log('closeUseEffect');
this.setState({
isShowUseEffect: !this.state.isShowUseEffect
})
}
render(){
const { isShowUseEffect } = this.state
return (
<div>app
isShowUseEffect - {isShowUseEffect}
{ isShowUseEffect ? <UseEffect ></UseEffect> : '' }
<div><button onClick={this.closeUseEffect}>关闭UseEffect组件</button></div>
</div>
)
}
}
useEffect.jsx
import React, { useEffect, useState } from 'react';
export default function UseEffect(props) {
const [timer, setTimer] = useState(null)
useEffect(()=>{
const interval = setInterval(()=>{
console.log('定时器执行');
setTimer(timer+1)
},1000)
return () => {
clearInterval(interval)
}
},[timer])
return (
<div className='content'>
UseEffect
timer - {timer}
</div>
)
}
效果
react 函数组件 03:使用useContext hook (访问上下文)
01:创建context上下文对象 LightContext.jsx
import { createContext } from 'react';
export const LightContext = createContext();
02:UseContext.jsx 当前爷组件提供 light数据和提供修改light的方法
import React, { useState } from 'react';
import A from "./A";
import { LightContext } from "./LightContext";
export default function UseContext(props) {
const [light,setLight] = useState({
bg: '#fff',
text: '白天'
})
return (
<LightContext.Provider value={{light,setLight}} >
<div className='content'>
UseContext的使用-{light.bg}
<A></A>
</div>
</LightContext.Provider>
)
}
03:A.jsx 在A组件修改 light数据,实现爷子孙 light数据同步更新
import React, { useContext } from 'react';
import ASon from "./ASon";
import { LightContext } from "./LightContext";
export default function A() {
const { light, setLight } = useContext(LightContext);
function changeLight() {
setLight(prevLight => ({ ...prevLight, bg: 'red' }));
}
return (
<div className='content'>
A组件-light-{light.bg} <button onClick={changeLight}>A组件修改了light</button>
<ASon></ASon>
</div>
)
}
04:ASon.jsx
import React, { useContext } from 'react';
import { LightContext } from "./LightContext";
export default function ASon(props) {
const {light} = useContext(LightContext);
return (
<div className='content'>
ASon组件 - { light.bg } - { light.text}
</div>
)
}
效果
react 函数组件 04:使用useRef hook (获取dom节点,实现input聚焦等)
code.jsx
import React, { useRef, useState } from 'react';
export default function UseRef(props) {
const [name,setName] = useState('')
const iptREf = useRef(null)
function nameChange(event){
setName(event.target.value)
}
function iptFocus(){
iptREf && iptREf.current.focus()
}
return (
<div className='content'>
<input type='text' value={name} onChange={nameChange} ref={iptREf}></input>
<div>
<button onClick={iptFocus}>input自动聚焦</button>
</div>
</div>
)
}
效果
react 函数组件 05:使用useLayoutEffect hook ( 副作用可用于初始化dom节点的宽高等=>echarts的宽高绘制等)
- useLayoutEffect它非常类似于 useEffect,但是在组件完成更新后立即同步执行,而不是在浏览器绘制之后异步执行。
- 作用:
- 在 DOM 更新完成后立即同步执行副作用操作,它被调用时会在浏览器执行绘制之前触发,因此可以获取到最新的 DOM 布局信息。
- 注意点:
- 由于 useLayoutEffect 是同步执行的,因此需要注意它可能会阻塞主线程,导致性能问题
code.jsx 初始化时,拿到浏览器窗口的宽度与高度写入dom节点
import React, { useState,useLayoutEffect } from 'react';
export default function UseLayoutEffect(props) {
const [size, setSize] = useState({width:0,height:0})
useLayoutEffect(()=>{
const handleResize = () => {
setSize({width:window.innerWidth, height:window.innerHeight});
};
window.addEventListener('resize', handleResize);
handleResize();
return () => window.removeEventListener('resize', handleResize);
},[])
return (
<div className='content' style={{width:size.width,height:size.height,background:'#ccc'}}>
useLayoutEffect - width - {size.width} - height-{size.height}
</div>
)
}
效果