React 组件通信

React组件通信方式总结:1)父传子通过props单向传递数据,子组件不能直接修改;2)子传父通过回调函数实现数据传递;3)兄弟组件通过状态提升到共同父组件实现通信;4)跨层组件可使用Context机制,通过Provider提供数据,useContext获取;5)复杂应用推荐Redux集中状态管理,通过createSlice创建reducer,Provider注入store,useSelector和useDispatch操作状态。Redux Toolkit简化了Redux使用流程,支持同步/异步操作。

  1. 父传子
    父组件通过 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>
  );
}
  1. 子传父

子组件通过 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>
  );
}
  1. 兄弟组件

使用状态提升实现兄弟组件通信,即通过共同的父组件传递

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>
  );
}
  1. 跨层组件通信------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>
  );
}
  1. 跨层组件通信------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>
  );
}
相关推荐
LYFlied6 小时前
【每日算法】 LeetCode 394. 字符串解码
前端·数据结构·算法·leetcode·面试·职场和发展
硕子鸽7 小时前
UniApp + Dify 实战:详解 SSE 流式响应的解析与前端渲染
前端·uni-app·dify
lxh01137 小时前
复原IP地址
前端·数据结构·算法
2301_796512527 小时前
React Native鸿蒙跨平台开发包含输入收入金额、选择收入类别、记录备注和日期等功能,实战react-native-paper组件
javascript·react native·react.js
Miketutu7 小时前
[特殊字符] uni-app App 端实现文件上传功能(基于 xe-upload 插件)
前端·vue.js·uni-app
San30.7 小时前
现代前端工程化实战:从 Vite 到 Vue Router 的构建之旅
前端·javascript·vue.js
sg_knight7 小时前
模块热替换 (HMR):前端开发的“魔法”与提速秘籍
前端·javascript·vue·浏览器·web·模块化·hmr
A24207349307 小时前
js常用事件
开发语言·前端·javascript
LV技术派7 小时前
适合很多公司和团队的 AI Coding 落地范式(一)
前端·aigc·ai编程