React组件通信方式总结:1)父传子通过props单向传递数据,子组件不能直接修改;2)子传父通过回调函数实现数据传递;3)兄弟组件通过状态提升到共同父组件实现通信;4)跨层组件可使用Context机制,通过Provider提供数据,useContext获取;5)复杂应用推荐Redux集中状态管理,通过createSlice创建reducer,Provider注入store,useSelector和useDispatch操作状态。Redux Toolkit简化了Redux使用流程,支持同步/异步操作。
- 父传子
父组件通过 props 传递数据给子组件,子组件通过 props 接收数据。
props 可以传递任意类型的数据,包括字符串、布尔值、函数、对象、数组、JSX 等。
// 父组件functionParent(){const[value,setValue]=useState("父组件传递的数据");return(<div><Child value={value}/></div>);}// 子组件functionChild(props:{value:string}){return<div>{props.value}</div>;}props 是只读的,不能直接修改,父组件的数据只能由父组件修改。
props children
// 父组件 标签嵌套<Son><span>我是span标签</span></Son>;// 子组件 通过props.children渲染在页面中functionSon(props:{children:React.ReactNode}){return(<div><h1>我是子组件</h1><hr/>{props.children}</div>);}- 子传父
子组件通过 props 传递数据给父组件,父组件通过 props 接收数据,并传递给子组件。
// 父组件functionParent(){const[value,setValue]=useState("");consthandleChildChange=(value:string)=>{setValue(value);};return(<div><Child onChange={handleChildChange}/><p>{value}</p></div>);}// 子组件functionChild(props:{onChange:(value:string)=>void}){const[value,setValue]=useState("");consthandleChange=(e:React.ChangeEvent<HTMLInputElement>)=>{setValue(e.target.value);props.onChange(e.target.value);};return(<div><input type="text"value={value}onChange={handleChange}/></div>);}- 兄弟组件
使用状态提升实现兄弟组件通信,即通过共同的父组件传递
// 父组件functionParent(){const[value,setValue]=useState("");consthandleChildChange=(value:string)=>{setValue(value);};return(<div><Child1 onChange={handleChildChange}/><Child2 value={value}/></div>);}// 子组件1functionChild1(props:{onChange:(value:string)=>void}){const[value,setValue]=useState("");consthandleChange=(e:React.ChangeEvent<HTMLInputElement>)=>{setValue(e.target.value);props.onChange(e.target.value);};return(<div><input type="text"value={value}onChange={handleChange}/></div>);}// 子组件2functionChild2(props:{value:string}){return(<div><p>{props.value}</p></div>);}- 跨层组件通信——Context 机制
// 1. 创建ContextconstMyContext=createContext();// 2. 顶层组件通过Provider组件提供数据functionParent(){const[value,setValue]=useState("");consthandleChildChange=(value:string)=>{setValue(value);};return(<MyContext.Provider value={value}><Child1 onChange={handleChildChange}/><Child2/></MyContext.Provider>);}// 3. 子组件通过useContext钩子获取数据functionChild2(){constvalue=useContext(MyContext);return(<div><p>{value}</p></div>);}- 跨层组件通信——Redux 机制 (集中状态管理工具)
// 1. 安装// Redux Toolkit:是一套工具集,用于简化 Redux 的书写方式// react-redux:链接React和Redux的中间件npm i @reduxjs/toolkit react-redux// 2. 创建slice store/modules/counterStore.jsimport{createSlice}from"@reduxjs/toolkit";importaxiosfrom"axios";constcounterSlice=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},},});constchannelSlice=createSlice({name:"channel",initialState:{channelList:[]},reducers:{// 获取异步数据setChannel(state,action){state.channelList=action.payload}}})// 解构actioncCreater函数const{increment,decrement,addToNum}=counterSlice.actions;const{setChannel}=channelSlice.actions;// 发起异步请求constgetChannelList=()=>{returnasync(dispatch)=>{constres=awaitaxios.get("http://localhost:3000/channel");dispatch(setChannel(res.data))}}constcountReducer=counterSlice.reducer;constchannelReducer=channelSlice.reducer;// 导出方法export{increment,decrement,addToNum,getChannelList};exportdefaultcountReducer;exportdefaultchannelReducer;// 3. 创建store store/index.jsimport{configureStore}from"@reduxjs/toolkit";importcounterReducerfrom"./counterSlice";importchannelReducerfrom"./channelSlice";conststore=configureStore({reducer:{counter:counterReducer,channel:channelReducer,},});exportdefaultstore;// 4. 在顶层组件中提供store App.jsimport{Provider}from"react-redux";importstorefrom"./store";createRoot(document.getElementById("root")).render(<StrictMode><Provider store={store}><App/></Provider></StrictMode>);// 5. 在子组件中获取store中的数据 useSelector:映射store中的数据 useDispatch:分发actionimport{useSelector,useDispatch}from"react-redux";import{increment,decrement,addToNum,getChannelList}from"./counterSlice";functionCounter(){// 映射store中的数据constcount=useSelector((state)=>state.counter);constlist=useSelector((state)=>state.channel);constdispatch=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>);}