使用react时,对于函数式组件,它是没有state的,所以当时被称为无状态的组件,Hook 是什么? Hook 是一个特殊的函数,它可以让你“钩入” React 的特性,使用hooks时,可以钩入其他函数,以便函数式的组件达到class定义的组件的作用效果。
1,useState()
使用useState()可以返回一个数组,包含着一个数据和一个函数,数据相当于class组件时定义的state里的数据,函数相当于setState(), 用于修改数据状态。
import { useState } from "react";
function Demo() {
// 声明一个叫 "count" 的 state 变量
// useState() 传入的值为 count 的初始值
// 另外的写法:
// const data = setCount(0)
// const count = data[0]
// const setCount = data[1]
const [count, setCount]= useState(0)
return (
<div>
<h2>数据为:{count}</h2>
// 使用 setCount() 改变 count 的状态
<button onClick={() => {setCount(count + 1)}}>click me</button>
</div>
)
}
如果我们想使用多个 state 变量,它允许我们给不同的 state 变量取不同的名称。
2,useEffect()
Effect Hook 可以让你在函数组件中执行副作用操作, 可以把 useEffect
Hook 看做 componentDidMount
,componentDidUpdate
和 componentWillUnmount
这三个函数的组合。
import { useEffect, useState } from "react";
export default function Effect() {
// 先声明变量 count
const [count, setCount] = useState(0)
// 点击改变 count 时,都会执行函数内的内容
useEffect(() => {
console.log('组件挂在了----', count);
})
return (
<div>
<h1>{count}</h1>
<button onClick={() => {setCount(count + 1)}}>click me</button>
</div>
)
}
import { useEffect, useState } from "react";
import { Routes, Route, Link } from 'react-router-dom'
// 组件一
function Demo1() {
useEffect(() => {
console.log('demo1挂载了---');
// 使用return 返回的函数,这里可以监听组件的销毁
return () => {
console.log('demo1被销毁了');
}
})
return (
<>
<h1>这是demo1</h1>
</>
)
}
// 组件二
function Demo2() {
useEffect(() => {
console.log('demo2挂载了---');
})
return (
<>
<h1>这是demo2</h1>
</>
)
}
// 组件三
function Index() {
useEffect(() => {
console.log('Index挂载了---');
})
return (
<>
<h1>这是Index</h1>
</>
)
}
export default function Effect() {
const [count, setCount] = useState(0)
useEffect(() => {
console.log('组件挂在了----');
},[]) // 添加 [] ,使函数内不在随着 count 的变化而继续执行,也可以使用,[count], 监听 count 的变化
return (
<div>
<h1>{count}</h1>
<button onClick={() => {setCount(count + 1)}}>click me</button>
<ul>
{/* 链接路由,显示出组件的销毁 */}
<li><Link to="/demo1">去demo1</Link></li>
<li><Link to="/demo2">去demo2</Link></li>
<li><Link to="/">默认</Link></li>
</ul>
{/* 配置路由规则 */}
<Routes>
<Route path="/demo1" element={<Demo1 />}></Route>
<Route path="/demo2" element={<Demo2 />}></Route>
<Route path="/" element={<Index />}></Route>
</Routes>
</div>
)
}
2,createContext(), useContext(), useReducer()
使用createContext()可以返回一个组件对象,以提供使用:
import {createContext, useState} from 'react'
export const colorContext = createContext()
export const UPDATE_COLOR = "UPDATE_COLOR"
// 使用 Color 组件包裹需要用到变量 color 的组件,props 参数接收的 children ,也就是包裹的那些组件,进而渲染,从而接受到传递的 value 两边的值。
export const Color = props => {
const [color, setColor] = useState('red')
return (
<div>
<colorContext.Provider value={{color}}>
{props.children}
</colorContext.Provider>
</div>
)
}
useContext()是需要数据的组件使用的,useContext()传入createContext()返回一个组件对象。从而取到 value 传递的值。
接收一个 context 对象(createContext()
的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider>
的 value
prop 决定。
可以实现祖孙组件数据的直接传递。
当组件上层最近的 <MyContext.Provider>
更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext
provider 的 context value
值。
// 引入 createContext() 返回的对象
import { colorContext } from "./color"
import { useContext } from "react"
export default function ContextDemo() {
const {color} = useContext(colorContext)
return (
<div>
<h1 style={{color}}>字体颜色为</h1>
</div>
)
}
useReducer(),传入两个参数,第一个为函数,第二个为初始值, useState 的替代方案。它接收一个形如 (state, action) => newState
的 reducer
reducer:
// state 为先前的状态值,初始值为使用 useReducer 传入的第二个参数值
// action为一个对象,包含行为和状态
const reducer = (state, action) => {
switch (action.type) {
case UPDATE_COLOR:
return action.color
default:
return state
}
}
使用时,返回当前的 state 以及与其配套的 dispatch
方法。使用 dispatch
传递一个action 对象,
包含一个 type 属性,和你要返回使用的状态值。
import { useReducer} from "react"
export default function ReduceDemo() {
const [color, dispatch] = useReducer(reducer, 'red')
return (
<div>
<button onClick={() => {dispatch({type: 'UPDATE_COLOR', color: 'deeppink'})}}>粉红色</button>
<button onClick={() => {dispatch({type: 'UPDATE_COLOR', color: 'green'})}}>绿色</button>
</div>
)
}
const reducer = (state, action) => {
switch (action.type) {
case UPDATE_COLOR:
console.log(state)
return action.color
default:
console.log(state)
}
}
三者搭配使用可以替代redux。
4,useMemo()
当子组件从父组件获取得到数据,当父组件的其他数据更新时,也会引起子组件的重新渲染耗费性能。
使用useMemo可以避免。
function Blue({blue}) {
function changeBlue(blue) {
console.log('Blue更新了');
return blue
}
const nBlue = useMemo(() => changeBlue(blue), [blue])
return (
<>
<h1>{nBlue}</h1>
</>
)
}