React 数据通信
一、组件间通信
1. 父组件向子组件通信
通过 Props 传递数据
jsxfunction Parent() { const data = "Hello"; return <Child message={data} />; } function Child({ message }) { return <div>{message}</div>; }
2. 子组件向父组件通信
通过回调函数传递数据
jsxfunction Parent() { const handleData = (data) => { console.log(data); }; return <Child onSendData={handleData} />; } function Child({ onSendData }) { return <button onClick={() => onSendData("Hello")}>Send</button>; }
3. 兄弟组件通信
通过共同的父组件传递数据
jsxfunction Parent() { const [data, setData] = useState(""); return ( <> <ChildA onSendData={setData} /> <ChildB message={data} /> </> ); } function ChildA({ onSendData }) { return <button onClick={() => onSendData("Hello")}>Send</button>; } function ChildB({ message }) { return <div>{message}</div>; }
二、跨层级通信
1. 使用 Context API
- 创建 Contextjsx
const MyContext = React.createContext();
- 提供数据jsx
function Parent() { const value = "Hello"; return ( <MyContext.Provider value={value}> <Child /> </MyContext.Provider> ); }
- 消费数据jsx
function Child() { const value = useContext(MyContext); return <div>{value}</div>; }
2. 使用 Redux
创建 Store
jsximport { createStore } from "redux"; const initialState = { message: "" }; function reducer(state = initialState, action) { switch (action.type) { case "UPDATE_MESSAGE": return { ...state, message: action.payload }; default: return state; } } const store = createStore(reducer);
提供 Store
jsximport { Provider } from "react-redux"; function App() { return ( <Provider store={store}> <Child /> </Provider> ); }
消费数据
jsximport { useSelector, useDispatch } from "react-redux"; function Child() { const message = useSelector((state) => state.message); const dispatch = useDispatch(); return ( <div> <div>{message}</div> <button onClick={() => dispatch({ type: "UPDATE_MESSAGE", payload: "Hello" })} > Update </button> </div> ); }
三、状态管理工具
1. Recoil
定义状态
jsximport { atom, useRecoilState } from "recoil"; const messageState = atom({ key: "messageState", default: "", });
使用状态
jsxfunction Child() { const [message, setMessage] = useRecoilState(messageState); return ( <div> <div>{message}</div> <button onClick={() => setMessage("Hello")}>Update</button> </div> ); }
2. MobX
定义 Store
jsximport { makeAutoObservable } from "mobx"; class MessageStore { message = ""; constructor() { makeAutoObservable(this); } setMessage(value) { this.message = value; } } const messageStore = new MessageStore();
使用 Store
jsximport { observer } from "mobx-react-lite"; const Child = observer(() => { return ( <div> <div>{messageStore.message}</div> <button onClick={() => messageStore.setMessage("Hello")}>Update</button> </div> ); });
四、常见面试问题与解决方案
1. 如何避免 Props Drilling?
- 使用 Context API:将数据提升到全局,避免逐层传递。
- 使用状态管理工具:如 Redux、Recoil、MobX。
2. 如何实现兄弟组件通信?
- 通过共同的父组件:将状态提升到父组件,通过 Props 和回调函数传递。
- 使用状态管理工具:如 Redux、Recoil。
3. Context API 和 Redux 的区别?
- Context API:适合小型应用或局部状态管理。
- Redux:适合大型应用,提供更强大的状态管理和调试工具。
4. 如何优化 Context 的性能?
- 拆分 Context:将不同状态拆分为多个 Context,避免不必要的渲染。
- 使用
useMemo
和useCallback
:缓存值和回调函数。
5. Redux 中间件的作用是什么?
- 处理异步操作:如
redux-thunk
或redux-saga
。 - 日志记录:如
redux-logger
。
五、综合示例
以下是一个使用 Context API 和 Redux 的综合示例:
jsx
// Context API 示例
const ThemeContext = React.createContext();
function App() {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
return <ThemedButton />;
}
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button
style={{ background: theme === "light" ? "#fff" : "#333" }}
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
>
Toggle Theme
</button>
);
}
// Redux 示例
import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";
const initialState = { count: 0 };
function reducer(state = initialState, action) {
switch (action.type) {
case "INCREMENT":
return { ...state, count: state.count + 1 };
default:
return state;
}
}
const store = createStore(reducer);
function Counter() {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return (
<div>
<div>{count}</div>
<button onClick={() => dispatch({ type: "INCREMENT" })}>Increment</button>
</div>
);
}
function App() {
return (
<Provider store={store}>
<Counter />
</Provider>
);
}
六、总结
React 中的数据通信方式包括:
- 组件间通信:Props、回调函数、Context API
- 跨层级通信:Context API、Redux、Recoil、MobX
- 状态管理工具:Redux(适合大型应用)、Recoil(轻量级)、MobX(响应式)