在 React 中,函数组件间的通信方式与类组件类似,但更多地依赖于函数式编程的特性。以下是几种常见的函数组件间通信方式,适用于父子组件、兄弟组件以及跨层级组件的场景。
1. 父子组件通信
(1)从父组件向子组件传递数据
通过 props 将数据从父组件传递到子组件。
示例代码:
tsx
// 父组件
import React from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const message = 'Hello from Parent!';
return <ChildComponent message={message} />;
};
export default ParentComponent;
// 子组件
import React from 'react';
const ChildComponent = ({ message }) => {
return <div>{message}</div>;
};
export default ChildComponent;
(2)从子组件向父组件传递数据
通过 回调函数 将数据从子组件传递到父组件。
示例代码:
tsx
// 父组件
import React, { useState } from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const [message, setMessage] = useState('');
const handleMessage = (msg) => {
setMessage(msg);
};
return (
<div>
<ChildComponent onMessage={handleMessage} />
<p>Message from Child: {message}</p>
</div>
);
};
export default ParentComponent;
// 子组件
import React from 'react';
const ChildComponent = ({ onMessage }) => {
const sendMessage = () => {
onMessage('Hello from Child!');
};
return <button onClick={sendMessage}>Send Message</button>;
};
export default ChildComponent;
2. 兄弟组件通信
兄弟组件之间不能直接通信,但可以通过共同的父组件来间接通信。
(1)通过父组件的状态和回调函数实现通信
示例代码:
tsx
// 父组件
import React, { useState } from 'react';
import SiblingA from './SiblingA';
import SiblingB from './SiblingB';
const ParentComponent = () => {
const [sharedData, setSharedData] = useState('');
return (
<div>
<SiblingA sharedData={sharedData} setSharedData={setSharedData} />
<SiblingB sharedData={sharedData} />
</div>
);
};
export default ParentComponent;
// 兄弟组件 A
import React from 'react';
const SiblingA = ({ sharedData, setSharedData }) => {
return (
<div>
<input
type="text"
value={sharedData}
onChange={(e) => setSharedData(e.target.value)}
/>
</div>
);
};
export default SiblingA;
// 兄弟组件 B
import React from 'react';
const SiblingB = ({ sharedData }) => {
return <div>{sharedData}</div>;
};
export default SiblingB;
3. 跨层级组件通信
当组件层级较深时,逐层传递 props 会变得繁琐,此时可以使用以下方法:
(1)Context API
通过 React 的 Context API 提供一个全局的上下文,供任意层级的组件访问。
示例代码:
tsx
// 创建 Context
import React, { createContext, useContext, useState } from 'react';
const MessageContext = createContext();
// 父组件
const ParentComponent = () => {
const [message, setMessage] = useState('Hello from Context');
return (
<MessageContext.Provider value={{ message, setMessage }}>
<ChildComponent />
</MessageContext.Provider>
);
};
export default ParentComponent;
// 子组件
const ChildComponent = () => {
return (
<div>
<GrandChildComponent />
</div>
);
};
// 孙子组件
const GrandChildComponent = () => {
const { message, setMessage } = useContext(MessageContext);
return (
<div>
<p>{message}</p>
<button onClick={() => setMessage('New Message from GrandChild')}>
Update Message
</button>
</div>
);
};
export default GrandChildComponent;
(2)状态管理库(如 Redux、MobX)
使用状态管理库来管理全局状态,组件可以通过连接状态管理库来读取或更新状态。
示例(以 Redux 为例):
tsx
// Redux store
import { createStore } from 'redux';
const initialState = {
message: 'Hello from Redux',
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'UPDATE_MESSAGE':
return { ...state, message: action.payload };
default:
return state;
}
};
const store = createStore(reducer);
// 父组件
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
return (
<Provider store={store}>
<ChildComponent />
</Provider>
);
};
export default ParentComponent;
// 子组件
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
const ChildComponent = () => {
const message = useSelector((state) => state.message);
const dispatch = useDispatch();
const updateMessage = () => {
dispatch({ type: 'UPDATE_MESSAGE', payload: 'New Message from Child' });
};
return (
<div>
<p>{message}</p>
<button onClick={updateMessage}>Update Message</button>
</div>
);
};
export default ChildComponent;
4. 使用事件总线(Event Bus)
通过一个全局的事件总线(如 EventEmitter
)在组件间发布和订阅事件。
示例代码:
tsx
// eventBus.js
import { EventEmitter } from 'events';
const eventBus = new EventEmitter();
export default eventBus;
// 父组件
import React from 'react';
import eventBus from './eventBus';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const handleMessage = (msg) => {
console.log('Message from Child:', msg);
};
React.useEffect(() => {
eventBus.on('message', handleMessage);
return () => {
eventBus.off('message', handleMessage);
};
}, []);
return <ChildComponent />;
};
export default ParentComponent;
// 子组件
import React from 'react';
import eventBus from './eventBus';
const ChildComponent = () => {
const sendMessage = () => {
eventBus.emit('message', 'Hello from Child!');
};
return <button onClick={sendMessage}>Send Message</button>;
};
export default ChildComponent;
总结
在 React 函数组件中,组件间通信的方式与类组件类似,但更多地依赖于函数式编程的特性。以下是几种常见的通信方式:
-
父子组件通信:
- 通过 props 从父组件向子组件传递数据。
- 通过 回调函数 从子组件向父组件传递数据。
-
兄弟组件通信:
- 通过共同的父组件的状态和回调函数实现。
-
跨层级组件通信:
- 使用 Context API 提供全局上下文。
- 使用 状态管理库(如 Redux、MobX)管理全局状态。
-
事件总线:
- 通过全局事件总线发布和订阅事件(较少使用,但适用于某些场景)。