React组件通信方式总结:1)父传子通过props单向传递数据,子组件不能直接修改;2)子传父通过回调函数实现数据传递;3)兄弟组件通过状态提升到共同父组件实现通信;4)跨层组件可使用Context机制,通过Provider提供数据,useContext获取;5)复杂应用推荐Redux集中状态管理,通过createSlice创建reducer,Provider注入store,useSelector和useDispatch操作状态。Redux Toolkit简化了Redux使用流程,支持同步/异步操作。
- 父传子
父组件通过 props 传递数据给子组件,子组件通过 props 接收数据。
props 可以传递任意类型的数据,包括字符串、布尔值、函数、对象、数组、JSX 等。
javascript
// 父组件
function Parent() {
const [value, setValue] = useState("父组件传递的数据");
return (
<div>
<Child value={value} />
</div>
);
}
// 子组件
function Child(props: { value: string }) {
return <div>{props.value}</div>;
}
props 是只读的,不能直接修改,父组件的数据只能由父组件修改。
props children
javascript
// 父组件 标签嵌套
<Son>
<span>我是span标签</span>
</Son>;
// 子组件 通过props.children渲染在页面中
function Son(props: { children: React.ReactNode }) {
return (
<div>
<h1>我是子组件</h1>
<hr />
{props.children}
</div>
);
}
- 子传父
子组件通过 props 传递数据给父组件,父组件通过 props 接收数据,并传递给子组件。
javascript
// 父组件
function Parent() {
const [value, setValue] = useState("");
const handleChildChange = (value: string) => {
setValue(value);
};
return (
<div>
<Child onChange={handleChildChange} />
<p>{value}</p>
</div>
);
}
// 子组件
function Child(props: { onChange: (value: string) => void }) {
const [value, setValue] = useState("");
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
props.onChange(e.target.value);
};
return (
<div>
<input type="text" value={value} onChange={handleChange} />
</div>
);
}
- 兄弟组件
使用状态提升实现兄弟组件通信,即通过共同的父组件传递
javascript
// 父组件
function Parent() {
const [value, setValue] = useState("");
const handleChildChange = (value: string) => {
setValue(value);
};
return (
<div>
<Child1 onChange={handleChildChange} />
<Child2 value={value} />
</div>
);
}
// 子组件1
function Child1(props: { onChange: (value: string) => void }) {
const [value, setValue] = useState("");
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
props.onChange(e.target.value);
};
return (
<div>
<input type="text" value={value} onChange={handleChange} />
</div>
);
}
// 子组件2
function Child2(props: { value: string }) {
return (
<div>
<p>{props.value}</p>
</div>
);
}
- 跨层组件通信------Context 机制
javascript
// 1. 创建Context
const MyContext = createContext();
// 2. 顶层组件通过Provider组件提供数据
function Parent() {
const [value, setValue] = useState("");
const handleChildChange = (value: string) => {
setValue(value);
};
return (
<MyContext.Provider value={value}>
<Child1 onChange={handleChildChange} />
<Child2 />
</MyContext.Provider>
);
}
// 3. 子组件通过useContext钩子获取数据
function Child2() {
const value = useContext(MyContext);
return (
<div>
<p>{value}</p>
</div>
);
}
- 跨层组件通信------Redux 机制 (集中状态管理工具)
javascript
// 1. 安装
// Redux Toolkit:是一套工具集,用于简化 Redux 的书写方式
// react-redux:链接React和Redux的中间件
npm i @reduxjs/toolkit react-redux
// 2. 创建slice store/modules/counterStore.js
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";
const counterSlice = createSlice({
name: "counter", // 命名空间
// 初始化状态
initialState: {
count: 0
},
// 定义修改状态的方法 同步方法 支持直接修改
reducers: {
increment(state) {
state.count ++;
},
decrement(state) {
state.count --;
},
// 支持传递参数 传递的参数会作为action.payload payload:固定的属性名
addToNum(state,action){
state.count+= action.payload
},
},
});
const channelSlice = createSlice({
name: "channel",
initialState: {
channelList: []
},
reducers: {
// 获取异步数据
setChannel(state,action){
state.channelList = action.payload
}
}
})
// 解构actioncCreater函数
const { increment, decrement,addToNum } = counterSlice.actions;
const { setChannel } = channelSlice.actions;
// 发起异步请求
const getChannelList = () => {
return async (dispatch)=>{
const res = await axios.get("http://localhost:3000/channel");
dispatch(setChannel(res.data))
}
}
const countReducer = counterSlice.reducer;
const channelReducer = channelSlice.reducer;
// 导出方法
export { increment, decrement, addToNum, getChannelList };
export default countReducer;
export default channelReducer;
// 3. 创建store store/index.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
import channelReducer from "./channelSlice";
const store = configureStore({
reducer: {
counter: counterReducer,
channel: channelReducer,
},
});
export default store;
// 4. 在顶层组件中提供store App.js
import { Provider } from "react-redux";
import store from "./store";
createRoot(document.getElementById("root")).render(
<StrictMode>
<Provider store={store}>
<App />
</Provider>
</StrictMode>
);
// 5. 在子组件中获取store中的数据 useSelector:映射store中的数据 useDispatch:分发action
import { useSelector, useDispatch } from "react-redux";
import { increment, decrement, addToNum, getChannelList } from "./counterSlice";
function Counter() {
// 映射store中的数据
const count = useSelector((state) => state.counter);
const list= useSelector((state) => state.channel);
const dispatch = useDispatch();
// 触发请求
useEffect(()=>{
dispatch(getChannelList())
},[dispatch])
return (
<div>
<p>{count}</p>
<button onClick={() => dispatch(increment())}>+</button>
<button onClick={() => dispatch(decrement())}>-</button>
{/* 传参 */}
<button onClick={() => dispatch(addToNum(10))}>+10</button>
{/* 数据列表 */}
<ul>
{list.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}