首页 > 其他分享 >多种 React 组件通信方式实践

多种 React 组件通信方式实践

时间:2024-01-13 18:32:24浏览次数:23  
标签:const 实践 React return 组件 import 弹窗

使用 React Context

基于 React Context 实现跨组件通信的一个常见用例是创建一个能够在不同组件间共享和触发行为的上下文。以下是一个简化的例子,展示了如何在 app.tsx 中触发其他组件(例如,一个弹窗组件)中的方法。

1. 创建一个 Context

首先,我们创建一个新的 Context。这个 Context 将包含我们想要在应用中共享的方法。

import React, { createContext, useContext } from 'react';

// 创建 Context
const MyContext = createContext({
  togglePopup: () => {}, // 这是一个示例方法
});

2. 创建一个 Context Provider

接下来,创建一个提供者组件,它将使得在应用的不同部分都能够访问到 Context 中的值。

export const MyProvider = ({ children }) => {
  const togglePopup = () => {
    // 这里实现弹窗的显示隐藏逻辑
    console.log("Toggle Popup called");
  };

  return (
    <MyContext.Provider value={{ togglePopup }}>
      {children}
    </MyContext.Provider>
  );
};

3. 在 app.tsx 中使用 Provider

在 app.tsx 中,用 MyProvider 包裹整个应用,使得任何子组件都能够访问 Context 中的值。

import React from 'react';
import { MyProvider } from './MyProvider'; // 引入刚才创建的 Provider

function App() {
  return (
    <MyProvider>
      {/* 应用的其余部分 */}
    </MyProvider>
  );
}

export default App;

4. 在子组件中使用 Context

最后,在需要的组件中使用这个 Context。例如,如果你有一个弹窗组件,你可以在其中使用这个 Context。

import React, { useContext } from 'react';
import { MyContext } from './MyContext';

const Popup = () => {
  const { togglePopup } = useContext(MyContext);

  return (
    <div>
      {/* 弹窗的内容 */}
      <button onClick={togglePopup}>关闭弹窗</button>
    </div>
  );
};

export default Popup;

在这个例子中我们创建了一个可以在整个应用中共享的 Context。我们定义了一个 togglePopup 方法,并在需要的组件中通过 Context 使用它。这种方式使得跨组件通信变得简单和模块化。

使用自定义事件

使用自定义事件进行组件间通信是一种非常灵活的方法。在 React 中,我们可以使用第三方库,如 mitt 或 eventemitter3 来实现这一机制。下面是一个基于此思想的实现示例。以下是使用 mitt 的示例。mitt 是一个轻量级的事件发射器/监听器库。

1.安装 mitt

使用 npm install mitt 安装事件监听器,然后创建一个 Event 实例,这个实例将在整个应用中共享。

import mitt from 'mitt';

const emitter = mitt();

export default emitter;

2.在 app.tsx 中触发事件

在 app.tsx 中,你可以触发一个自定义事件,这个事件将被其他组件监听和响应。

import React from 'react';
import emitter from './emitter';

function App() {
  const openPopup = () => {
    emitter.emit('togglePopup', true);
  };

  return (
    <div>
      <button onClick={openPopup}>打开弹窗</button>
      {/* 其他组件 */}
    </div>
  );
}

export default App;

3.在其他组件中监听事件

在你的公共组件(例如一个弹窗组件)中,监听之前在 app.tsx 中触发的事件。

import React, { useEffect, useState } from 'react';
import emitter from './emitter';

const Popup = () => {
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    const toggleListener = (state) => {
      setIsOpen(state);
    };

    emitter.on('togglePopup', toggleListener);

    return () => {
      emitter.off('togglePopup', toggleListener);
    };
  }, []);

  if (!isOpen) return null;

  return (
    <div>
      {/* 弹窗内容 */}
      <button onClick={() => setIsOpen(false)}>关闭弹窗</button>
    </div>
  );
};

export default Popup;

这个例子展示了如何使用 mitt 来实现跨组件通信。这种方法对于那些不便于通过 props 或 state 进行传递的复杂交互特别有用。它还可以帮助你减少对全局状态管理解决方案的依赖,从而使组件保持更加解耦和可重用。

使用 React Ref

使用 React Ref 实现组件间的方法调用是一种直接且有效的方式,尤其适用于父组件需要直接调用子组件中的方法的场景。以下是一个使用 React Ref 实现的示例。

1.创建子组件并暴露方法

首先,创建一个子组件并使用 useImperativeHandle 与 forwardRef 来暴露特定的方法。

import React, { useImperativeHandle, forwardRef } from 'react';

const Popup = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    openPopup: () => {
      console.log("弹窗打开");
      // 弹窗打开的逻辑
    },
    closePopup: () => {
      console.log("弹窗关闭");
      // 弹窗关闭的逻辑
    }
  }));

  return (
    <div>这里是弹窗的内容</div>
  );
});

export default Popup;

2.在父组件中使用 Ref 调用方法

接下来,在父组件中创建一个 ref,并将其传递给子组件。然后,使用这个 ref 来调用子组件中的方法。

import React, { useRef } from 'react';
import Popup from './Popup';

function App() {
  const popupRef = useRef();

  const openPopup = () => {
    popupRef.current.openPopup();
  };

  const closePopup = () => {
    popupRef.current.closePopup();
  };

  return (
    <div>
      <button onClick={openPopup}>打开弹窗</button>
      <button onClick={closePopup}>关闭弹窗</button>
      <Popup ref={popupRef} />
    </div>
  );
}

export default App;

使用 React Ref 来调用子组件的方法是一个非常直观和简单的方法,特别适合于需要直接从父组件控制子组件行为的场景。它允许父组件通过 ref 直接访问子组件的实例

使用 Redux 实现组件间通信

Redux 是一种流行的状态管理库,适用于大型 React 应用。通过 Redux,你可以在应用的不同部分共享状态和逻辑。以下是一个简化的例子,展示如何使用 Redux 来更新和访问应用状态。

1.设置 Redux

首先,你需要设置 Redux 的基本元素:store、reducers 和 actions。

// actions.js
export const togglePopup = () => ({
  type: 'TOGGLE_POPUP'
});

// reducer.js
const initialState = {
  isPopupOpen: false
};

export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'TOGGLE_POPUP':
      return { ...state, isPopupOpen: !state.isPopupOpen };
    default:
      return state;
  }
};

// store.js
import { createStore } from 'redux';
import { reducer } from './reducer';

export const store = createStore(reducer);

2.在 app.tsx 中使用 Redux

使用 Redux 的 Provider 来包裹你的应用,并在需要的地方通过 dispatch 触发 action。

import React from 'react';
import { Provider } from 'react-redux';
import { store } from './store';
import { togglePopup } from './actions';
import Popup from './Popup';

function App() {
  return (
    <Provider store={store}>
      <button onClick={() => store.dispatch(togglePopup())}>
        切换弹窗状态
      </button>
      <Popup />
    </Provider>
  );
}

export default App;

3.在其他组件中连接 Redux

在需要的组件中使用 connect 函数(或 useSelector 和 useDispatch 钩子)来访问和更新 Redux 的状态。

import React from 'react';
import { connect } from 'react-redux';

const Popup = ({ isPopupOpen }) => {
  if (!isPopupOpen) return null;

  return (
    <div>弹窗内容</div>
  );
};

const mapStateToProps = state => ({
  isPopupOpen: state.isPopupOpen
});

export default connect(mapStateToProps)(Popup);

Redux 提供一个集中的存储,用于管理整个应用的状态。这对于大型应用来说是非常有用的,因为它可以避免状态在多个组件之间的重复传递。Redux 通过将逻辑集中和模块化,提高了代码的维护性和扩展性。且拥有广泛的中间件和生态系统,支持异步操作、日志记录、持久化等高级功能。

使用 Callbacks 实现组件间通信

通过 props 向子组件传递回调函数是 React 中最基本的通信方式之一。

1.在父组件中定义和传递 Callback

import React, { useState } from 'react';
import Popup from './Popup';

function App() {
  const [isPopupOpen, setIsPopupOpen] = useState(false);

  const togglePopup = () => {
    setIsPopupOpen(!isPopupOpen);
  };

  return (
    <div>
      <button onClick={togglePopup}>切换弹窗状态</button>
      <Popup isOpen={isPopupOpen} onClose={togglePopup} />
    </div>
  );
}

export default App;

2.在子组件中使用 Callback

import React from 'react';

const Popup = ({ isOpen, onClose }) => {
  if (!isOpen) return null;

  return (
    <div>
      弹窗内容
      <button onClick={onClose}>关闭</button>
    </div>
  );
};

export default Popup;

对于简单的父子组件通信,使用回调函数是直接且简单的,它避免了引入额外的库或复杂的架构。以保持组件的独立性和可重用性,因为子组件不需要关心状态是如何被管理的,只需关注它如何响应这些回调。

回调方法不需要任何额外的状态管理库或上下文,这使得应用更轻量,减少了依赖和引入的复杂性。对于小型或不太复杂的应用,使用回调进行状态管理通常足够,并且可以避免过度设计。

标签:const,实践,React,return,组件,import,弹窗
From: https://blog.51cto.com/u_11365839/9232952

相关文章

  • 实验七:Spark机器学习库Mtlib编程实践
    1、数据导入导入相关的jar包:importorg.apache.spark.ml.feature.PCAimportorg.apache.spark.sql.Rowimportorg.apache.spark.ml.linalg.{Vector,Vectors}importorg.apache.spark.ml.evaluation.MulticlassClassificationEvaluatorimportorg.apache.spark.ml.{Pipeline,......
  • TVM编译器原理与实践
    目录前言TVM编译器的实现过程关于《TVM编译器原理与实践》编辑推荐内容简介作者简介图书目录书中前言/序言《TVM编译器原理与实践》全书速览结束语前言随着人工智能的发展,计算机视觉、自然语言处理和语音识别等领域的需求不断增加。为了更好地满足这些需求,许多深度学习框架被开发出......
  • 如何让spring扫描到自定义注解的组件
    ClassPathScanningCandidateComponentProviderscanner=newClassPathScanningCandidateComponentProvider(true);scanner.addIncludeFilter(newAnnotationTypeFilter(Tenant.class));Set<BeanDefinition>beanDefinitions=scanner.findCandidat......
  • Flutter 自定义一个右侧可滑动 左侧为按钮的组件
    Flutter自定义一个右侧可滑动左侧为按钮的组件vartopicList=["圈子话题1","圈子话题2","圈子话题3","圈子话题4-天气很好","圈子话题5","圈子话题6"];@overrideWidgetbuild(BuildContextcontext){returnSizedBox(height:40......
  • 小程序开发:在插件市场寻找步骤条组件并二开
    想实现一个可滚动的步骤条用来显示自己的随笔作为一名全栈工程师,要是全部都自己写,那太废时间了,首先去uniapp的插件市场逛逛看有没有符合需要的组件先:第一个: 看着符合自己的要求了,该有的有了,但是感觉左边的色调太单调了,故pass。第二个: 这个看起来颜色就比较丰富一些了,右边......
  • 运动控制理论(2)——实践例子
     目的:要知道末端点的位置。直观的向量法最直接的办法,以向量相加的形式求。 *3个向量都是参考0系构建。坐标转换法 p1 是以1系下的局部坐标。R是旋转矩阵,各列是以0系为参考的正交基。v1是平移向量,也是以0系为参考的。合并起来变成了T。T=R3*3t3*3 ,将旋转和平......
  • 2024-01-13 antd的tabel组件业务问题之勾选了table中的一项,然后弹出弹窗,接着关闭弹窗,
    如图:问题:table显示的勾选状态的数据无法被改变。原因:你没有改变到勾选数据,你只是在勾选时把选中的值赋值给了一个变量,然后以为自己清空了变量,以为自然而然地就取消勾选状态了,实际上就是你代码没写全!解决方案:原来写法:rowSelection:{onChange:handleChange,},你写......
  • 2024-01-13 Can't perform a React state update on an unmounted component. This i
    react+antd业务代码报错: Can'tperformaReactstateupdateonanunmountedcomponent.Thisisano-op,butitindicatesamemoryleakinyourapplication.Tofix,cancelallsubscriptionsandasynchronoustasksinauseEffectcleanupfunction.无法对未安装的......
  • Windows 10 中,可以使用 PowerShell 添加打印和文件服务的角色功能组件,包括 Internet
    在Windows10中,可以使用PowerShell添加打印和文件服务的角色功能组件,包括Internet打印客户端、LPD打印服务和LPR端口监视器。以下是添加这些功能组件的PowerShell命令:首先,以管理员身份打开PowerShell终端。在开始菜单中搜索"PowerShell",然后右键点击"WindowsPo......
  • 基于 Aidlux的智慧教育版面分析场景下的实践
    基于Aidlux的智慧教育版面分析场景下的实践基于Aidlux的智慧教育版面分析应用一、Aidlux环境介绍所有代码均可通过加课程小助手wx获得:AidLux_Me官网:https://aidlux.com/1.产品优势AidLux是基于ARM架构的跨生态(Android/鸿蒙+Linux)一站式AIoT应用快速开发和部署平台APP。......