目录
1. useState - 让函数组件具有维持状态的能力
? ? ? ? 1.1 语法
? ? ? ? 1.2 应用? ?
2. useEffect? -? 执行副作用
? ? ? ? 2.1 语法
? ? ? ? 2.2 应用
? ? ? ? 2.3 关于依赖项
????????2.4 小案例
? ? ? ? 2.5 小总结
3. useContext - 定义全局状态
? ? ? ? 3.1 Context机制
? ? ? ? 3.2 使用步骤
4. 综合小案例 - 改变主题
? ? ? ? ? ? ?
useState、useEffect和useContext是在项目中使用频率比较高的三个内置Hooks。下面来介绍一下三个Hooks的基本用法和使用场景,以及与使用Class组件时的一些区别。
注意:Hooks只能在函数式组件中使用哦
1. useState - 让函数组件具有维持状态的能力
? ? ? ? 1.1 语法
const [state, setState] = useState(initialState)
// useState钩子函数返回值为数组,其第一个元素是用来读取state值,第二个是用来设置state值的方法
// initialState 作为参数是设置state的初始值
// 设置
setState(newStateValue)
? ? ? ? 1.2 应用? ?
????????一般第二个参数以set+state值名字来命名,这样语义上表意,且统一。比如:
// 保存一个“主题”的值,为一个对象
const [theme, setTheme] = useState({}); // theme = {}
// 上述代码表示,设置一个state值名为theme,设置其值的方法为setTheme,其初始值为{}
// 修改theme的值
setTheme({background:'#fcfcfc'}); // theme = {background:'#fcfcfc'}
// 对比Class组件中修改state的方式
state = {
theme: {}
}
this.setState({
theme:{background:'#fcfcfc'}
})
2. useEffect? -? 执行副作用
如果对Class组件的生命周期熟悉,可以把useEffect Hook看作是 componentDidMount 、componentDidUpdate、componentWillUnmounted三个生命周期函数的组合。
? ? ? ? 2.1 语法
useEffect(callback, dependencies)
// callback是要执行的函数
// dependencies是可选的依赖数组
? ? ? ? 2.2 应用
import React, {useEffect} from 'react';
const Demo = () => {
useEffect(()=>{
// 组件在首次渲染和更新时执行
console.log(' componentDidMount 组件已经被渲染到DOM中')
console.log(' componentDidUpdate 组件已经更新')
// 组件在卸载前执行
// 允许返回一个函数,用于在组件销毁时做一些清理工作,如:移除事件监听 == componentWillUnmount
return ()=>{console.log(' componentWillUnmounted 组件即将被卸载')}
},[deps])
return (
<div>demo</div>
)
}
? ? ? ? 2.3 关于依赖项
? ? ? ? ????????1)deps表示依赖项,只有当依赖项发生变化时才会执行以上代码 ? ? ? ? ? ? ? ? 2)当不指定依赖项时,则会在每次函数组件执行完后执行 ? ? ? ? ????????3)空数组作为依赖项,只在首次执行时触发 === componentDidMount
????????2.4 小案例
// 需求:根据参数id获取对应blog内容
import React, {useState, useEffect} from 'react'
const BlogView = ({id}:{id:number})=>{
const [blogContent, setBlogContent] = useState(null);
useEffect(()=>{
// useEffect的callback要避免直接的async函数,需封装一下
const doAsync = async ()=>{
setBlogContent(null); // id变化,清除当前内容
const res = await fetch(`/blog-content/${id}`);
setBlogContent(await res.text());
}
doAsync();
},[id])
const isLoading = !blogContent;
return <div>{isLoading?"Loading...":blogContent}</div>
}
? ? ? ? 2.5 小总结
1. 每次render后执行:无依赖
useEffect(()=>{})
2. 仅第一次render后执行:依赖空数组
useEffect(()=>{},[])
3. 第一次以及依赖项变化后执行:提供依赖项数组
useEffect(()=>{},[deps])
4. 组件unmount后执行:返回一个回调函数
useEffect(()=>{return ()=>{}},[])
3. useContext - 定义全局状态
useContext与Context API使用基本相同,只是在使用值的组件中对值的获取方式不同。
? ? ? ? 3.1 Context机制
????????Context:让所有在某个组件开始的组件树上创建一个Context。这个组件树上的所有组件都能访问和修改这个Context了。
????????很多状态管理框架,如Redux利用了Context的机制来提供一种更加可控的组件之间的状态管理机制。
? ? ? ? 3.2 使用步骤
const count = 1;
// 1)创建一个Context,从某个组件为根组件的组件树上可用 - React.createContext?
const CountContext = React.CreateContext(count)
// 2)ThemeContext具有Provider属性,一般作为组件树的根组件 - ThemeContext.Provider
const App = () => {
// themes.dark 是作为一个属性值传给 Provider 组件,其下面的子组件都可以接收到值
return (
// Provider
<ThemeContext.Provider value={count}>
<ContextDemo />
</ThemeContext.Provider>
);
}
// 3)在用到数据的地方使用useContext获取数据
const ContextDemo = () => {
// 使用useContext获取CountContext传下来的值
const count = useContext(CountContext);
return (
<div>{count}</div> // count = 1
);
}
4. 综合小案例 - 改变主题
// 根组件中
import React, { useCallback, useState } from "react";
import ContextDemo from "./pages/ContextDemo";
// 定义两种主题可切换
const themes = {
light: {
foreground: "#000",
background: "#eee",
},
dark: {
foreground: "#fff",
background: "#222",
},
};
export const ThemeContext = React.createContext(themes.light);
function App() {
// 使用 state 来保存 theme 从而可以动态修改
const [theme, setTheme] = useState('dark');
// 切换主题的函数
const toggleTheme = () => {
setTheme(theme === 'dark' ? 'light' : 'dark');
};
return (
// 使用 theme state 作为当前 Context
<ThemeContext.Provider value={themes[theme]}>
<button onClick={toggleTheme}>changeTheme</button>
<ContextDemo />
</ThemeContext.Provider>
);
}
// 子组件中
import React, { useContext } from "react";
import { ThemeContext } from "../../App";
const ContextDemo = () => {
// 在 Theme Button 中使用 useContext 来获取当前的主题
const themes = useContext(ThemeContext);
console.log(themes);
return (
<div>
<button
style={{
backgroundColor: themes.background,
color: themes.foreground,
border: 0,
}}
>
useContext Demo
</button>
</div>
);
};
export default ContextDemo;
? ? ? ? ? ? ?
|