React Hooks API 演示
目录
1. useState() 管理组件状态
useState()有两个参数,第一个为该 state 的值, 第二个是管理该状态的函数.
import React, { useState } from "react"
const App = () => {
const [authForm, setAuthForm] = useState({
username: "",
password: "",
})
const handleChange = event => {
const { name, value } = event.target
setAuthForm(prevState => ({
...prevState,
[name]: value,
}))
}
return (
<>
<input
name="username"
value={authForm.username}
onChange={handleChange}
/>
<input
name="password"
value={authForm.password}
onChange={handleChange}
/>
</>
)
}
export default App
1.1 表单逻辑 Hooks Demo
例如上面的表单authForm
, 可以单独封装为一个表单逻辑 Hooks 专门处理表单输入.
useFrom.js
import { useState } from "react"
const useForm = initState => {
const [form, setForm] = useState(initState)
return [
form,
event => {
setForm({
...form,
[event.target.name]: event.target.value,
})
},
]
}
export default useForm
App.js
因为我们在useForm
中返回的是一个数组, 因此命名不需要与useForm
中的匹配, 我们是用下标取相对应的参数. (下标 0 第一个就是 state, 下标 1 为管理 state 的函数)
import React, { useState } from "react"
import { useForm } from "./useForm"
export const App = () => {
const [authForm, setAuthForm] = useForm({
username: "",
email: "",
password: "",
})
return (
<>
<input name="username" value={authForm.username} onChange={setAuthForm} />
<input name="password" value={authForm.password} onChange={setAuthForm} />
<input name="email" value={authForm.email} onChange={setAuthForm} />
</>
)
}
1.2 自定义 Counter Demo
useCounter.jsx
import React, { useState } from "react"
const useCounter = initState => {
const [count, setCount] = useState(initState)
const increment = (payload = 0) => {
setCount(prevCnt => prevCnt + payload)
}
return [count, increment]
}
export default useCounter
App.jsx
import React, { useState } from "react"
import useCounter from "./useCounter"
const App = () => {
const [count, setCount] = useCounter(10)
return (
<div className="app-container">
<p>{count}</p>
<button onClick={setCount}>Increment</button>
</div>
)
}
export default App
2. useEffect() 管理生命周期
之前在 class 组件中可以利用componentDidMount
以及其他函数来管理 state 的生命周期。现在可以利用 useEffect 来管理组件的渲染或者处理第三方 API 的请求数据。
useEffect()
中有两个参数,第一个回调函数即要执行的操作。第二个参数为 effect 触发的依赖,当依赖发生变化时就会执行 useEffect。
Effect Dependencies []
可有0 个或者多个参数.
0 个参数 []
类似于componentDidMount
即组件第一次渲染时触发.
多个参数则只要任意一个依赖更新了则会触发 effect
useEffect(() => {
//action
}, [dependencies])
2.1 API Data Fetching 封装 Hooks Demo
如果是POST
或者之后还需要fetchSubject
, 返回的第二个参数也可以填入.
useSubjectApi.js
import { useState, useEffect } from "react"
const useSubjectApi = subject_id => {
const [subject, setSubject] = useState()
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)
useEffect(() => {
const fetchSubject = async () => {
try {
const response = await fetch(
`https://api.bgm.tv/subject/${subject_id}?responseGroup=large`
)
const data = await response.json()
setSubject(data)
} catch (err) {
setError(true)
}
setLoading(false)
}
fetchSubject()
}, [URL])
const res = {
subject,
loading,
error,
}
return [res] // 这里只用来GET 所以只返回数据
}
export default useSubjectApi
App.js
import React, { useState, useEffect } from "react"
import useSubjectApi from "./Hooks/useSubjectApi"
const App = () => {
const [data] = useSubjectApi(51)
if (data.error || data.loading) {
return <p>Loading...</p>
}
const subject = data.subject
return (
<>
<h1>{subject.name}</h1>
<img src={subject.images.large} style={{ width: 150 }} />
</>
)
}
export default App
3. useContext(): 跨组件传递状态
- 创建相关状态, 命名例如
UserContext
, 可初始化状态或者初始化为null
- 在需要的父级层面用
Provider
提供数据 - 在需要状态的子级组件用
useContext
来作为Consumer
接受数据
UserContext.js
import { createContext } from "react"
export const UserContext = createContext(null)
以之前创建的UserContext
作为提供者(Provider), 所有的子级组件都可以用useContext
来获取 Provider 的 state
App.js
import React, { useState, useEffect } from "react"
import { UserContext } from "./Context/UserContext"
import Dashboard from "./Components/Dashboard"
import ProfileMenu from "./Components/ProfileMenu"
const App = () => {
return (
<UserContext.Provider
value={{
userName: "yang_tk",
status: "online",
}}
>
<>
<ProfileMenu />
<Dashboard />
</>
</UserContext.Provider>
)
}
export default App
然后我们就可以在 ProfileMenu 和 Dashboard 中引用我们UserNameContext
的 state
ProfileMenu.js
import React, { useContext } from "react"
import { UserContext } from "../Context/UserContext"
const ProfileMenu = () => {
const user = useContext(UserContext)
return (
<>
<h1>This is profile menu</h1>
<p>{user.userName}</p>
<p>{user.status}</p>
</>
)
}
export default ProfileMenu
Dashboard.js
import React, { useContext } from "react"
import { UserContext } from "../Context/UserContext"
const Dashboard = () => {
const { userName } = useContext(UserContext)
return (
<>
<h1>This is dashboard</h1>
<p>Welcome back {userName}</p>
</>
)
}
export default Dashboard
4. useReducer(): 状态管理
首先来看一下 useReducer()的参数
const [state, dispatch] = useReducer(reducer, initialState)
- state 即函数的状态值
- dispath 则是用来打包相关的行为
- reducer 即我们我们之后 Reducer 的函数
- initialState 为状态的初始值
counterReducer.js
const counterReducer = (state, action) => {
switch (action.type) {
case "INCREMENT":
return {
...state,
count: state.count + 1,
}
case "DECREMENT":
return {
...state,
count: state.count - 1,
}
case "RESET":
return {
...state,
count: 0,
}
default:
return state
}
}
export default counterReducer
App.js
import { counterReducer } from "./reducers/counterReducer"
const App = () => {
const initState = {
count: 0,
}
const [state, dispatch] = useReducer(counterReducer, initState)
return (
<>
<button onClick={() => dispatch({ type: "increment" })}>Increment</button>
<button onClick={() => dispatch({ type: "decrement" })}>Decrement</button>
<button onClick={() => dispatch({ type: "reset" })}>Reset</button>
<p>{state.count}</p>
</>
)
}
export default App