useState
React 中的 useState 详解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - useState</title>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState } = React;
function Counter() {
const [count, setCount] = useState(0);
const [name, setName] = useState("React");
return (
<div>
<h2>Hook 入门:useState</h2>
<p>当前计数:{count}</p>
<button onClick={() => setCount(count + 1)}>点击 +1</button>
<button onClick={() => setCount(count - 1)}>点击 -1</button>
<div style={{ marginTop: 20 }}>
<p>当前名称:{name}</p>
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
/>
</div>
</div>
);
}
ReactDOM.render(<Counter />, document.getElementById("example"));
</script>
</body>
</html>
useEffect
React 中的 useEffect 详解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - useEffect</title>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState, useEffect, useRef } = React;
function Timer() {
const [time, setTime] = useState(new Date().toLocaleTimeString());
const inputRef = useRef(null);
useEffect(() => {
const timer = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
useEffect(() => {
document.title = "当前时间:" + time;
}, [time]);
return (
<div>
<h2>Hook 入门:useEffect + useRef</h2>
<p>当前时间:{time}</p>
<input ref={inputRef} defaultValue="Hello Hook" />
<button onClick={() => inputRef.current.focus()}>聚焦输入框</button>
</div>
);
}
ReactDOM.render(<Timer />, document.getElementById("example"));
</script>
</body>
</html>
useRef
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - useRef</title>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useRef, useState, useEffect } = React;
function InputFocusDemo() {
const inputRef = useRef(null);
const [count, setCount] = useState(0);
useEffect(() => {
console.log("inputRef.current:", inputRef.current);
}, [count]);
return (
<div>
<h2>Hook 进阶:useRef</h2>
<input ref={inputRef} type="text" defaultValue="Hello React" />
<button onClick={() => inputRef.current && inputRef.current.focus()}>
聚焦输入框
</button>
<p>点击次数:{count}</p>
<button onClick={() => setCount(count + 1)}>更新计数</button>
</div>
);
}
ReactDOM.render(<InputFocusDemo />, document.getElementById("example"));
</script>
</body>
</html>
useCallback
React 中的 useCallback 详解
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - useCallback</title>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState, useCallback, memo } = React;
const Child = memo(function Child({ onClick, count }) {
console.log("Child render");
return <button onClick={onClick}>子组件点击:{count}</button>;
});
function Parent() {
const [count, setCount] = useState(0);
const [other, setOther] = useState(0);
const handleClick = useCallback(() => {
setCount((prev) => prev + 1);
}, []);
return (
<div>
<h2>Hook 进阶:useCallback</h2>
<p>父组件其他状态:{other}</p>
<button onClick={() => setOther(other + 1)}>更新其他状态</button>
<Child onClick={handleClick} count={count} />
</div>
);
}
ReactDOM.render(<Parent />, document.getElementById("example"));
</script>
</body>
</html>
customHook
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - Custom Hook</title>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState, useEffect } = React;
function useWindowSize() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return size;
}
function WindowSizeDemo() {
const size = useWindowSize();
return (
<div>
<h2>Hook 进阶:自定义 Hook</h2>
<p>窗口宽度:{size.width}</p>
<p>窗口高度:{size.height}</p>
</div>
);
}
ReactDOM.render(<WindowSizeDemo />, document.getElementById("example"));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - Form Demo</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 30px;
}
.card {
width: 360px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
}
input, button {
margin-top: 10px;
width: 100%;
box-sizing: border-box;
padding: 8px;
}
button {
cursor: pointer;
}
</style>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState } = React;
function UserForm() {
const [form, setForm] = useState({
username: "",
password: "",
});
const handleChange = (key) => (event) => {
setForm((prev) => ({
...prev,
[key]: event.target.value,
}));
};
const handleSubmit = (event) => {
event.preventDefault();
alert(`用户名:${form.username}\n密码:${form.password}`);
};
return (
<div className="card">
<h2>Hook 实战:表单处理</h2>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="用户名"
value={form.username}
onChange={handleChange("username")}
/>
<input
type="password"
placeholder="密码"
value={form.password}
onChange={handleChange("password")}
/>
<button type="submit">提交</button>
</form>
</div>
);
}
ReactDOM.render(<UserForm />, document.getElementById("example"));
</script>
</body>
</html>
combine-demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - Combined Demo</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 30px;
}
.box {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
width: 420px;
}
button {
margin-right: 8px;
padding: 8px 12px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState, useEffect, useRef, useCallback } = React;
function useTimer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setSeconds((prev) => prev + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
return seconds;
}
function CombinedDemo() {
const seconds = useTimer();
const [count, setCount] = useState(0);
const inputRef = useRef(null);
const increase = useCallback(() => {
setCount((prev) => prev + 1);
}, []);
const reset = useCallback(() => {
setCount(0);
}, []);
useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, [count]);
return (
<div>
<div className="box">
<h2>Hook 实战:组合使用</h2>
<p>计时器:{seconds} 秒</p>
<p>计数器:{count}</p>
<button onClick={increase}>加 1</button>
<button onClick={reset}>重置</button>
</div>
<div className="box">
<input ref={inputRef} defaultValue="聚焦状态" />
</div>
</div>
);
}
ReactDOM.render(<CombinedDemo />, document.getElementById("example"));
</script>
</body>
</html>
useFetch
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - useFetch</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 30px;
}
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
width: 420px;
}
button {
padding: 8px 16px;
margin-top: 12px;
cursor: pointer;
}
ul {
padding-left: 20px;
}
</style>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState, useEffect } = React;
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
let isMounted = true;
async function fetchData() {
try {
setLoading(true);
const response = await fetch(url);
const result = await response.json();
if (isMounted) {
setData(result);
setError(null);
}
} catch (err) {
if (isMounted) {
setError(err.message || "请求失败");
}
} finally {
if (isMounted) {
setLoading(false);
}
}
}
fetchData();
return () => {
isMounted = false;
};
}, [url]);
return { data, loading, error };
}
function FetchDemo() {
const { data, loading, error } = useFetch("https://jsonplaceholder.typicode.com/posts?_limit=3");
if (loading) return <div className="card">正在加载...</div>;
if (error) return <div className="card">错误:{error}</div>;
return (
<div className="card">
<h2>Hook 实战:useFetch</h2>
<ul>
{data && data.map((item) => <li key={item.id}>{item.title}</li>)}
</ul>
</div>
);
}
ReactDOM.render(<FetchDemo />, document.getElementById("example"));
</script>
</body>
</html>
useLocalStorage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>React Hook - useLocalStorage</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 30px;
}
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
width: 420px;
}
input, button {
width: 100%;
box-sizing: border-box;
margin-top: 10px;
padding: 8px;
}
</style>
</head>
<body>
<div id="example"></div>
<script src="https://cdn.jsdelivr.net/npm/react@16.14.0/umd/react.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@16.14.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@7.23.2/babel.min.js"></script>
<script type="text/babel">
const { useState, useEffect } = React;
function useLocalStorage(key, initialValue) {
const [value, setValue] = useState(() => {
const storedValue = localStorage.getItem(key);
return storedValue ? JSON.parse(storedValue) : initialValue;
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue];
}
function LocalStorageDemo() {
const [name, setName] = useLocalStorage("hook-demo-name", "React");
return (
<div className="card">
<h2>Hook 实战:useLocalStorage</h2>
<input
type="text"
value={name}
onChange={(event) => setName(event.target.value)}
/>
<button onClick={() => localStorage.removeItem("hook-demo-name")}>清除缓存</button>
</div>
);
}
ReactDOM.render(<LocalStorageDemo />, document.getElementById("example"));
</script>
</body>
</html>