组件通信 - 知蛛网父子组件通信
父传子 - Props
// 父组件
function ParentComponent() {
const [count, setCount] = useState(0);
const userData = {
name: "张三",
age: 25,
email: "zhangsan@example.com",
};
return (
<div>
<h1>父组件</h1>
<ChildComponent count={count} user={userData} isActive={true} onUpdate={handleUpdate} />
</div>
);
}
// 子组件
function ChildComponent({ count, user, isActive, onUpdate }) {
return (
<div>
<h2>子组件</h2>
<p>计数: {count}</p>
<p>用户名: {user.name}</p>
<p>状态: {isActive ? "活跃" : "非活跃"}</p>
<button onClick={() => onUpdate("新的数据")}>更新数据</button>
</div>
);
}
子传父 - 回调函数
// 父组件
function ParentComponent() {
const [message, setMessage] = useState("");
const [items, setItems] = useState([]);
// 处理子组件传递的数据
const handleChildData = data => {
console.log("接收到子组件数据:", data);
setMessage(data.message);
};
const handleAddItem = newItem => {
setItems([...items, newItem]);
};
const handleDeleteItem = itemId => {
setItems(items.filter(item => item.id !== itemId));
};
return (
<div>
<h1>父组件</h1>
<p>来自子组件的消息: {message}</p>
{/* 传递回调函数给子组件 */}
<ChildComponent onDataSend={handleChildData} onAddItem={handleAddItem} items={items} />
{/* 多个子组件通信 */}
<ItemList items={items} onDeleteItem={handleDeleteItem} />
</div>
);
}
// 子组件1
function ChildComponent({ onDataSend, onAddItem, items }) {
const [inputValue, setInputValue] = useState("");
const sendDataToParent = () => {
// 向父组件发送数据
onDataSend({
message: inputValue,
timestamp: new Date().toISOString(),
});
};
const addNewItem = () => {
const newItem = {
id: Date.now(),
name: inputValue || `项目 ${items.length + 1}`,
};
onAddItem(newItem);
setInputValue("");
};
return (
<div>
<h2>子组件</h2>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入消息..."
/>
<button onClick={sendDataToParent}>发送消息给父组件</button>
<button onClick={addNewItem}>添加项目</button>
</div>
);
}
// 子组件2
function ItemList({ items, onDeleteItem }) {
return (
<div>
<h3>项目列表</h3>
<ul>
{items.map(item => (
<li key={item.id}>
{item.name}
<button onClick={() => onDeleteItem(item.id)}>删除</button>
</li>
))}
</ul>
</div>
);
}
通过 ref 直接操作子组件
import { useRef, forwardRef, useImperativeHandle } from "react";
// 子组件(使用 forwardRef)
const ChildComponent = forwardRef((props, ref) => {
const [value, setValue] = useState("");
const inputRef = useRef();
// 向父组件暴露方法
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
clear: () => {
setValue("");
inputRef.current.value = "";
},
getValue: () => {
return value;
},
setValue: newValue => {
setValue(newValue);
inputRef.current.value = newValue;
},
}));
return (
<div>
<input
ref={inputRef}
value={value}
onChange={e => setValue(e.target.value)}
placeholder="输入内容..."
/>
<p>当前值: {value}</p>
</div>
);
});
// 父组件
function ParentComponent() {
const childRef = useRef();
const handleFocus = () => {
childRef.current.focus();
};
const handleClear = () => {
childRef.current.clear();
};
const handleGetValue = () => {
const value = childRef.current.getValue();
alert(`当前值: ${value}`);
};
const handleSetValue = () => {
childRef.current.setValue("预设值");
};
return (
<div>
<h1>父组件</h1>
<ChildComponent ref={childRef} />
<div style={{ marginTop: "20px" }}>
<button onClick={handleFocus}>聚焦子组件输入框</button>
<button onClick={handleClear} style={{ marginLeft: "10px" }}>
清空
</button>
<button onClick={handleGetValue} style={{ marginLeft: "10px" }}>
获取值
</button>
<button onClick={handleSetValue} style={{ marginLeft: "10px" }}>
设置值
</button>
</div>
</div>
);
}
兄弟组件通信
通过父组件中转(状态提升)
function ParentComponent() {
const [sharedData, setSharedData] = useState("共享数据");
const [messages, setMessages] = useState([]);
// 更新共享数据
const updateSharedData = newData => {
setSharedData(newData);
};
// 添加消息
const addMessage = message => {
setMessages([
...messages,
{
id: Date.now(),
content: message,
timestamp: new Date().toLocaleTimeString(),
},
]);
};
return (
<div>
<h1>兄弟组件通信 - 通过父组件中转</h1>
<div style={{ display: "flex", gap: "20px", marginTop: "20px" }}>
{/* 兄弟组件1 */}
<BrotherComponentA
sharedData={sharedData}
onUpdateData={updateSharedData}
onSendMessage={addMessage}
/>
{/* 兄弟组件2 */}
<BrotherComponentB
sharedData={sharedData}
messages={messages}
onUpdateData={updateSharedData}
onSendMessage={addMessage}
/>
</div>
</div>
);
}
// 兄弟组件A
function BrotherComponentA({ sharedData, onUpdateData, onSendMessage }) {
const [inputValue, setInputValue] = useState("");
const handleUpdate = () => {
onUpdateData(inputValue || "来自组件A的更新");
};
const handleSendMessage = () => {
onSendMessage(`组件A发送: ${inputValue}`);
setInputValue("");
};
return (
<div style={{ padding: "20px", border: "1px solid #ccc", flex: 1 }}>
<h2>组件A</h2>
<p>共享数据: {sharedData}</p>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入内容..."
/>
<div style={{ marginTop: "10px" }}>
<button onClick={handleUpdate}>更新共享数据</button>
<button onClick={handleSendMessage} style={{ marginLeft: "10px" }}>
发送消息给组件B
</button>
</div>
</div>
);
}
// 兄弟组件B
function BrotherComponentB({ sharedData, messages, onUpdateData, onSendMessage }) {
const [inputValue, setInputValue] = useState("");
const handleUpdate = () => {
onUpdateData(inputValue || "来自组件B的更新");
};
const handleSendMessage = () => {
onSendMessage(`组件B发送: ${inputValue}`);
setInputValue("");
};
return (
<div style={{ padding: "20px", border: "1px solid #ccc", flex: 1 }}>
<h2>组件B</h2>
<p>共享数据: {sharedData}</p>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入内容..."
/>
<div style={{ marginTop: "10px" }}>
<button onClick={handleUpdate}>更新共享数据</button>
<button onClick={handleSendMessage} style={{ marginLeft: "10px" }}>
发送消息给组件A
</button>
</div>
<h3>消息记录</h3>
<ul>
{messages.map(message => (
<li key={message.id}>
{message.content} <small>({message.timestamp})</small>
</li>
))}
</ul>
</div>
);
}
使用 Context(适合深度嵌套兄弟组件)
import { createContext, useContext, useState } from "react";
// 创建 Context
const BrotherContext = createContext();
function ParentComponent() {
const [sharedState, setSharedState] = useState({
data: "初始共享数据",
messages: [],
counter: 0,
});
// 更新函数
const updateData = newData => {
setSharedState(prev => ({
...prev,
data: newData,
}));
};
const addMessage = message => {
setSharedState(prev => ({
...prev,
messages: [
...prev.messages,
{
id: Date.now(),
content: message,
timestamp: new Date().toLocaleTimeString(),
},
],
}));
};
const incrementCounter = () => {
setSharedState(prev => ({
...prev,
counter: prev.counter + 1,
}));
};
return (
<BrotherContext.Provider
value={{
...sharedState,
updateData,
addMessage,
incrementCounter,
}}
>
<div>
<h1>兄弟组件通信 - 使用 Context</h1>
<div style={{ display: "flex", gap: "20px", marginTop: "20px" }}>
<BrotherComponentC />
<BrotherComponentD />
</div>
{/* 深层嵌套的组件也可以访问 */}
<NestedComponent />
</div>
</BrotherContext.Provider>
);
}
// 兄弟组件C - 使用 Context
function BrotherComponentC() {
const context = useContext(BrotherContext);
const [inputValue, setInputValue] = useState("");
const handleUpdate = () => {
context.updateData(`来自组件C: ${inputValue}`);
};
const handleSendMessage = () => {
context.addMessage(`组件C说: ${inputValue}`);
setInputValue("");
};
return (
<div style={{ padding: "20px", border: "1px solid #ccc", flex: 1 }}>
<h2>组件C (使用Context)</h2>
<p>共享数据: {context.data}</p>
<p>计数器: {context.counter}</p>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入内容..."
/>
<div style={{ marginTop: "10px" }}>
<button onClick={handleUpdate}>更新数据</button>
<button onClick={handleSendMessage} style={{ marginLeft: "10px" }}>
发送消息
</button>
<button onClick={context.incrementCounter} style={{ marginLeft: "10px" }}>
增加计数
</button>
</div>
</div>
);
}
// 兄弟组件D - 使用 Context
function BrotherComponentD() {
const context = useContext(BrotherContext);
const [inputValue, setInputValue] = useState("");
const handleUpdate = () => {
context.updateData(`来自组件D: ${inputValue}`);
};
const handleSendMessage = () => {
context.addMessage(`组件D说: ${inputValue}`);
setInputValue("");
};
return (
<div style={{ padding: "20px", border: "1px solid #ccc", flex: 1 }}>
<h2>组件D (使用Context)</h2>
<p>共享数据: {context.data}</p>
<p>计数器: {context.counter}</p>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入内容..."
/>
<div style={{ marginTop: "10px" }}>
<button onClick={handleUpdate}>更新数据</button>
<button onClick={handleSendMessage} style={{ marginLeft: "10px" }}>
发送消息
</button>
<button onClick={context.incrementCounter} style={{ marginLeft: "10px" }}>
增加计数
</button>
</div>
<h3>消息记录</h3>
<ul>
{context.messages.map(message => (
<li key={message.id}>
{message.content} <small>({message.timestamp})</small>
</li>
))}
</ul>
</div>
);
}
// 深层嵌套组件
function NestedComponent() {
const context = useContext(BrotherContext);
return (
<div style={{ padding: "20px", marginTop: "20px", border: "1px solid #ddd" }}>
<h3>深层嵌套组件</h3>
<p>也可以访问共享数据: {context.data}</p>
<p>消息数量: {context.messages.length}</p>
</div>
);
}
跨层级组件通信
使用 Context API(推荐)
import { createContext, useContext, useState, useCallback } from "react";
// 创建多个 Context
const ThemeContext = createContext();
const UserContext = createContext();
const NotificationContext = createContext();
function App() {
const [theme, setTheme] = useState("light");
const [user, setUser] = useState({ name: "张三", role: "user" });
const [notifications, setNotifications] = useState([]);
// 添加通知
const addNotification = useCallback((message, type = "info") => {
const notification = {
id: Date.now(),
message,
type,
timestamp: new Date().toLocaleTimeString(),
};
setNotifications(prev => [notification, ...prev.slice(0, 4)]);
}, []);
// 移除通知
const removeNotification = useCallback(id => {
setNotifications(prev => prev.filter(n => n.id !== id));
}, []);
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<UserContext.Provider value={{ user, setUser }}>
<NotificationContext.Provider
value={{ notifications, addNotification, removeNotification }}
>
<div className={`app ${theme}`}>
<Header />
<div style={{ display: "flex" }}>
<Sidebar />
<MainContent />
</div>
<Footer />
</div>
</NotificationContext.Provider>
</UserContext.Provider>
</ThemeContext.Provider>
);
}
// Header 组件
function Header() {
const { theme, setTheme } = useContext(ThemeContext);
const { user } = useContext(UserContext);
const { addNotification } = useContext(NotificationContext);
const toggleTheme = () => {
const newTheme = theme === "light" ? "dark" : "light";
setTheme(newTheme);
addNotification(`主题已切换为${newTheme === "dark" ? "暗色" : "亮色"}模式`, "success");
};
const sendNotification = () => {
addNotification(`来自${user.name}的系统通知`, "info");
};
return (
<header style={{ padding: "20px", backgroundColor: theme === "dark" ? "#333" : "#f0f0f0" }}>
<h1>应用标题</h1>
<div>
<span>当前用户: {user.name}</span>
<button onClick={toggleTheme} style={{ marginLeft: "20px" }}>
切换主题
</button>
<button onClick={sendNotification} style={{ marginLeft: "10px" }}>
发送通知
</button>
</div>
</header>
);
}
// Sidebar 组件
function Sidebar() {
const { theme } = useContext(ThemeContext);
const { user, setUser } = useContext(UserContext);
const { addNotification } = useContext(NotificationContext);
const updateUserRole = () => {
const newRole = user.role === "user" ? "admin" : "user";
setUser({ ...user, role: newRole });
addNotification(`用户角色已更新为${newRole}`, "warning");
};
return (
<aside
style={{
width: "200px",
padding: "20px",
backgroundColor: theme === "dark" ? "#222" : "#e8e8e8",
}}
>
<h3>侧边栏</h3>
<p>当前角色: {user.role}</p>
<button onClick={updateUserRole}>切换角色</button>
</aside>
);
}
// MainContent 组件
function MainContent() {
const { theme } = useContext(ThemeContext);
const { user } = useContext(UserContext);
const { notifications, removeNotification } = useContext(NotificationContext);
return (
<main style={{ flex: 1, padding: "20px" }}>
<h2>主要内容</h2>
<p>当前主题: {theme}</p>
<p>
用户信息: {user.name} ({user.role})
</p>
<div style={{ marginTop: "30px" }}>
<h3>通知中心</h3>
{notifications.length === 0 ? (
<p>暂无通知</p>
) : (
<ul>
{notifications.map(notification => (
<li
key={notification.id}
style={{
padding: "10px",
margin: "5px 0",
backgroundColor:
notification.type === "success"
? "#d4edda"
: notification.type === "warning"
? "#fff3cd"
: notification.type === "error"
? "#f8d7da"
: "#d1ecf1",
borderLeft: `4px solid ${
notification.type === "success"
? "#28a745"
: notification.type === "warning"
? "#ffc107"
: notification.type === "error"
? "#dc3545"
: "#17a2b8"
}`,
}}
>
<span>{notification.message}</span>
<small style={{ marginLeft: "10px", color: "#666" }}>
{notification.timestamp}
</small>
<button
onClick={() => removeNotification(notification.id)}
style={{ marginLeft: "10px", float: "right" }}
>
关闭
</button>
</li>
))}
</ul>
)}
</div>
</main>
);
}
// Footer 组件
function Footer() {
const { theme } = useContext(ThemeContext);
return (
<footer
style={{
padding: "20px",
backgroundColor: theme === "dark" ? "#333" : "#f0f0f0",
marginTop: "20px",
}}
>
<p>页脚内容</p>
</footer>
);
}
使用自定义事件(Event Bus)
// eventBus.js - 事件总线
class EventBus {
constructor() {
this.events = {};
}
// 监听事件
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
// 移除监听
off(event, callback) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
// 触发事件
emit(event, data) {
if (!this.events[event]) return;
this.events[event].forEach(callback => callback(data));
}
// 只监听一次
once(event, callback) {
const onceCallback = data => {
callback(data);
this.off(event, onceCallback);
};
this.on(event, onceCallback);
}
}
// 创建全局事件总线实例
export const eventBus = new EventBus();
// ComponentA.jsx
import { useState, useEffect } from "react";
import { eventBus } from "./eventBus";
function ComponentA() {
const [messages, setMessages] = useState([]);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
// 监听来自其他组件的消息
const handleMessage = data => {
setMessages(prev => [
...prev,
{
id: Date.now(),
from: data.from,
message: data.message,
timestamp: new Date().toLocaleTimeString(),
},
]);
};
// 监听全局事件
eventBus.on("global.message", handleMessage);
eventBus.on("componentA.specific", data => {
console.log("ComponentA 特定事件:", data);
});
// 清理监听
return () => {
eventBus.off("global.message", handleMessage);
eventBus.off("componentA.specific");
};
}, []);
const sendMessage = () => {
// 发送全局消息
eventBus.emit("global.message", {
from: "ComponentA",
message: inputValue,
});
setInputValue("");
};
const sendToComponentB = () => {
// 发送给特定组件
eventBus.emit("componentB.specific", {
from: "ComponentA",
message: "专门给ComponentB的消息",
});
};
return (
<div style={{ padding: "20px", border: "1px solid blue" }}>
<h2>组件A</h2>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入消息..."
/>
<button onClick={sendMessage} style={{ marginLeft: "10px" }}>
广播消息
</button>
<button onClick={sendToComponentB} style={{ marginLeft: "10px" }}>
发送给组件B
</button>
<h3>收到的消息:</h3>
<ul>
{messages.map(msg => (
<li key={msg.id}>
<strong>{msg.from}:</strong> {msg.message}
<small>({msg.timestamp})</small>
</li>
))}
</ul>
</div>
);
}
// ComponentB.jsx
import { useState, useEffect } from "react";
import { eventBus } from "./eventBus";
function ComponentB() {
const [messages, setMessages] = useState([]);
const [componentAMessages, setComponentAMessages] = useState([]);
const [inputValue, setInputValue] = useState("");
useEffect(() => {
// 监听全局消息
const handleGlobalMessage = data => {
setMessages(prev => [
...prev,
{
id: Date.now(),
...data,
timestamp: new Date().toLocaleTimeString(),
},
]);
};
// 监听专门发给ComponentB的消息
const handleSpecificMessage = data => {
setComponentAMessages(prev => [
...prev,
{
id: Date.now(),
...data,
timestamp: new Date().toLocaleTimeString(),
},
]);
};
eventBus.on("global.message", handleGlobalMessage);
eventBus.on("componentB.specific", handleSpecificMessage);
return () => {
eventBus.off("global.message", handleGlobalMessage);
eventBus.off("componentB.specific", handleSpecificMessage);
};
}, []);
const sendMessage = () => {
eventBus.emit("global.message", {
from: "ComponentB",
message: inputValue,
});
setInputValue("");
};
const requestDataFromComponentC = () => {
// 请求-响应模式
eventBus.emit("request.data", {
requestId: Date.now(),
from: "ComponentB",
type: "userData",
});
};
return (
<div style={{ padding: "20px", border: "1px solid green" }}>
<h2>组件B</h2>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入消息..."
/>
<button onClick={sendMessage} style={{ marginLeft: "10px" }}>
广播消息
</button>
<button onClick={requestDataFromComponentC} style={{ marginLeft: "10px" }}>
请求数据
</button>
<h3>全局消息:</h3>
<ul>
{messages.map(msg => (
<li key={msg.id}>
<strong>{msg.from}:</strong> {msg.message}
<small>({msg.timestamp})</small>
</li>
))}
</ul>
<h3>来自ComponentA的消息:</h3>
<ul>
{componentAMessages.map(msg => (
<li key={msg.id}>
<strong>{msg.from}:</strong> {msg.message}
<small>({msg.timestamp})</small>
</li>
))}
</ul>
</div>
);
}
// ComponentC.jsx
import { useState, useEffect } from "react";
import { eventBus } from "./eventBus";
function ComponentC() {
const [requests, setRequests] = useState([]);
useEffect(() => {
// 监听数据请求
const handleRequest = data => {
setRequests(prev => [...prev, data]);
// 模拟异步响应
setTimeout(() => {
eventBus.emit(`response.${data.requestId}`, {
requestId: data.requestId,
from: "ComponentC",
data: {
users: [
{ id: 1, name: "张三" },
{ id: 2, name: "李四" },
],
},
});
}, 500);
};
eventBus.on("request.data", handleRequest);
return () => {
eventBus.off("request.data", handleRequest);
};
}, []);
return (
<div style={{ padding: "20px", border: "1px solid red" }}>
<h2>组件C (数据提供者)</h2>
<p>接收到的请求:</p>
<ul>
{requests.map(req => (
<li key={req.requestId}>
{req.from} 请求 {req.type}
</li>
))}
</ul>
</div>
);
}
// App.jsx
function App() {
return (
<div style={{ display: "flex", gap: "20px", padding: "20px" }}>
<ComponentA />
<ComponentB />
<ComponentC />
</div>
);
}
状态管理库通信
// store.js
import { configureStore, createSlice } from "@reduxjs/toolkit";
// 创建 counter slice
const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
// 创建 user slice
const userSlice = createSlice({
name: "user",
initialState: {
name: "张三",
age: 25,
isLoggedIn: false,
},
reducers: {
login: state => {
state.isLoggedIn = true;
},
logout: state => {
state.isLoggedIn = false;
},
updateUser: (state, action) => {
return { ...state, ...action.payload };
},
},
});
// 创建 store
export const store = configureStore({
reducer: {
counter: counterSlice.reducer,
user: userSlice.reducer,
},
});
// 导出 actions
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export const { login, logout, updateUser } = userSlice.actions;
// App.jsx
import { Provider, useDispatch, useSelector } from "react-redux";
import { store } from "./store";
function App() {
return (
<Provider store={store}>
<div style={{ padding: "20px" }}>
<h1>Redux 状态管理示例</h1>
<CounterComponent />
<UserComponent />
<ProductComponent />
</div>
</Provider>
);
}
// CounterComponent.jsx
function CounterComponent() {
const dispatch = useDispatch();
const count = useSelector(state => state.counter.value);
const [inputValue, setInputValue] = useState("");
return (
<div style={{ padding: "20px", border: "1px solid #ccc", marginBottom: "20px" }}>
<h2>计数器组件</h2>
<p>当前计数: {count}</p>
<button onClick={() => dispatch(increment())}>增加</button>
<button onClick={() => dispatch(decrement())} style={{ marginLeft: "10px" }}>
减少
</button>
<div style={{ marginTop: "10px" }}>
<input
type="number"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入增加值"
/>
<button
onClick={() => {
dispatch(incrementByAmount(Number(inputValue) || 0));
setInputValue("");
}}
style={{ marginLeft: "10px" }}
>
增加指定值
</button>
</div>
</div>
);
}
// UserComponent.jsx
function UserComponent() {
const dispatch = useDispatch();
const user = useSelector(state => state.user);
const [nameInput, setNameInput] = useState("");
const [ageInput, setAgeInput] = useState("");
return (
<div style={{ padding: "20px", border: "1px solid #ccc", marginBottom: "20px" }}>
<h2>用户组件</h2>
<p>用户名: {user.name}</p>
<p>年龄: {user.age}</p>
<p>登录状态: {user.isLoggedIn ? "已登录" : "未登录"}</p>
<div style={{ marginTop: "10px" }}>
<button onClick={() => dispatch(login())}>登录</button>
<button onClick={() => dispatch(logout())} style={{ marginLeft: "10px" }}>
退出
</button>
</div>
<div style={{ marginTop: "10px" }}>
<input
type="text"
value={nameInput}
onChange={e => setNameInput(e.target.value)}
placeholder="新用户名"
style={{ marginRight: "10px" }}
/>
<input
type="number"
value={ageInput}
onChange={e => setAgeInput(e.target.value)}
placeholder="新年龄"
/>
<button
onClick={() => {
dispatch(
updateUser({
name: nameInput || user.name,
age: ageInput ? Number(ageInput) : user.age,
})
);
setNameInput("");
setAgeInput("");
}}
style={{ marginLeft: "10px" }}
>
更新用户信息
</button>
</div>
</div>
);
}
// ProductComponent.jsx - 跨组件访问状态
function ProductComponent() {
const count = useSelector(state => state.counter.value);
const user = useSelector(state => state.user);
return (
<div style={{ padding: "20px", border: "1px solid #ccc" }}>
<h2>商品组件</h2>
<p>当前计数(来自计数器): {count}</p>
<p>当前用户(来自用户组件): {user.name}</p>
<p>商品价格: {count * 10}元</p>
<p>用户状态: {user.isLoggedIn ? "登录用户享受折扣" : "请先登录"}</p>
</div>
);
}
通信模式选择指南
| 场景 | 推荐方案 | 说明 |
|---|
| 父子组件 | Props + 回调函数 | 简单直接,React 标准方式 |
| 兄弟组件 | 状态提升到父组件 | 组件关系简单时使用 |
| 跨层级组件 | Context API | 避免 props drilling |
| 全局状态 | Redux/Zustand | 复杂应用状态管理 |
| 实时通信 | 自定义事件/Event Bus | 松散耦合的组件间通信 |
| 表单/复杂状态 | useReducer + Context | 状态逻辑复杂时 |
| 性能敏感 | useMemo + useCallback | 避免不必要的重新渲染 |
最佳实践总结
- 保持单向数据流:数据从父组件流向子组件,事件从子组件流向父组件
- 最小化 props:只传递必要的 props,避免过度传递
- 合理使用 Context:避免 Context 滥用,只在真正需要时使用
- 状态提升:当多个组件需要共享状态时,将状态提升到最近的共同祖先
- 自定义 Hooks:封装复杂的状态逻辑和副作用
- 类型安全:使用 TypeScript 或 PropTypes 确保通信的安全性
- 性能优化:使用 memo、useMemo、useCallback 避免不必要的渲染
- 错误边界:在关键通信路径上添加错误处理