基于React编写一个全局Toast的示例代码

 更新时间:2024年05月11日 08:28:11   作者:卸任  
前些日子在做项目的时候,需要封装一个Toast组件,我想起之前用过的库,只要在入口文件中引入就可以在全局中使用,还是很方便的,借这次机会也来实现一下,所以本文介绍了React中如何编写一个全局Toast,需要的朋友可以参考下

前言

前些日子在做项目的时候,需要封装一个Toast组件。我想起之前用过的库,只要在入口文件中引入就可以在全局中使用,还是很方便的,借这次机会也来实现一下。说起来也算是forwardRefuseImperativeHanleuseContext的实际使用。

  • 第一种,使用forwardRefuseImperativeHanle

一个是像react-toastify库一样使用,在入口处放置ToastContainer,然后在代码中任意地方使用toast("Wow so easy!")都有提示

  import React from 'react';

  import { ToastContainer, toast } from 'react-toastify';
  import 'react-toastify/dist/ReactToastify.css';
  
  function App(){
    const notify = () => toast("Wow so easy!");

    return (
      <div>
        <button onClick={notify}>Notify!</button>
        <ToastContainer />
      </div>
    );
  }
  • 第二种,使用useContext

在入口处放置ToastProvider,然后在代码中任意地方使用 const { show } = useToast()都有提示。忘记什么库了。

文中就用antdmessage来模拟一下我们自己写的Toast组件。

正文

我们先来了解一下forwardRefuseImperativeHanleuseContext的基本使用。

forwardRefuseImperativeHandle 的基本使用

forwardRefuseImperativeHandle,它们通常一起使用,以便在父组件中暴露子组件的特定方法或属性。

forwardRef,它允许你将父组件的ref转发到子组件中的某个 DOM 节点或其他 React 组件。这样,父组件就可以访问子组件的引用,并直接操作它。

useImperativeHandle 是一个自定义 Hook,它允许你自定义通过 forwardRef 暴露给父组件的 ref 值。你可以指定哪些方法属性被暴露,而不是直接暴露整个 DOM 节点或组件实例。

下面是一个简单的例子

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

const ChildComponent = forwardRef((props, ref) => {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));

  return <input ref={inputRef} {...props} />;
});

const ParentComponent = () => {
  const childRef = useRef(null);

  const handleClick = () => {
    childRef.current.focus();
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Focus Child Input</button>
    </div>
  );
};

export default ParentComponent;

使用forwardRef和useImperativeHanle封装全局Toast

封装组件

import React, { createRef, forwardRef, useImperativeHandle } from 'react';
import { Button, message } from 'antd';

const Toast = forwardRef((props, ref) => {
  const [messageApi, contextHolder] = message.useMessage();

  useImperativeHandle(ref, () => ({
    show: (msg: string) => {
      messageApi.info(msg);
    }
  }));

  return <>
    {contextHolder}
  </>
})

const ToastRef = createRef<{ show: (msg: string) => {} }>();

export const ToastContain = () => {
  return <Toast ref={ToastRef} />
}

export const showToast = (msg: string) => {
  if (ToastRef.current) {
    ToastRef.current.show(msg)
  }
};

在入口中引入

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import router from '@/router/index'
import reportWebVitals from './reportWebVitals';
import { RouterProvider } from 'react-router-dom';
import ErrorBoundary from './ErrorBoundary';
import { ToastContain } from './components/Toast';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
      <ToastContain />
      <RouterProvider router={router} fallbackElement={<div>准备中</div>} />
  </React.StrictMode>
);
reportWebVitals();

然后就可以在全局中使用 showToast方法了

import React from 'react';
import { showToast } from '../../../components/Toast';

export default function Index() {
  return <>
    <div
      onClick={() => {
        showToast('sadasds')
      }}
    >
       提示弹窗
    </div>
  </>
}

useContext的基本使用

useContext用于访问组件树中某个层级上定义的 ContextContext 提供了一种在组件之间共享值的方式,而不必通过组件树的每个层级显式传递 props

  • 创建 Context

首先,你需要创建一个 Context 对象。这可以通过调用 React.createContext 来完成。你还可以为默认值提供一个参数,如果 ContextProvider 没有在组件树中找到,将使用这个默认值。

import React from 'react';

const MyContext = React.createContext('defaultValue');

  • 提供 Context

你需要在组件树中的某个地方提供这个 Context。这通常在组件的顶层完成,通过使用 MyContext.Provider组件,并传递一个 value prop

import React from 'react';
import MyComponent from './MyComponent';
import { MyContext } from './MyContext';

function App() {
  return (
    <MyContext.Provider value="Hello from Context">
      <MyComponent />
    </MyContext.Provider>
  );
}

export default App;

  • 使用 useContext

在需要访问 Context 的组件中,你可以使用 useContext Hook 来获取 Context 的当前值

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

function MyComponent() {
  const contextValue = useContext(MyContext);

  return <p>Context value: {contextValue}</p>;
}

export default MyComponent;

使用useContext来封装全局Toast

封装组件

import React, { createContext, useCallback, useContext, useState } from 'react';
import { Button, message } from 'antd';

const ToastContext = createContext<any>(null);

export const ToastProvider = ({ children }: any) => {
  const [messageApi, contextHolder] = message.useMessage();

  const show = useCallback((msg: string) => {
    messageApi.info(msg);
  }, [messageApi]);

  return (
    <ToastContext.Provider value={{ show }}>
      {children}
      {contextHolder}
    </ToastContext.Provider>
  );
};

export const useToast = () => {
  const context = useContext(ToastContext);
  return context;
};

在入口处使用

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import router from '@/router/index'
import reportWebVitals from './reportWebVitals';
import { RouterProvider } from 'react-router-dom';
import ErrorBoundary from './ErrorBoundary';
import { ToastProvider } from './components/ToastOne';

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <ToastProvider>
      <RouterProvider router={router} fallbackElement={<div>准备中</div>} />
    </ToastProvider>
  </React.StrictMode>
);

然后就可以通过useToast在全局中使用了

import React from 'react';
import { useToast } from '../../../components/ToastOne';

export default function Index() {
  const { show } = useToast()

  return <>
    <div
      onClick={() => {
        show('guiyu')
      }}
    >
      点击提示
    </div>
  </>
}

结尾

以上就是基于React编写一个全局Toast的示例代码的详细内容,更多关于React编写全局Toast的资料请关注脚本之家其它相关文章!

相关文章

  • React中的函数式插槽详解

    React中的函数式插槽详解

    这篇文章主要为大家详细介绍了React 开发中遇到的具名插槽的函数用法,文中的示例代码讲解详细,具有一定的学习价值,有兴趣的小伙伴可以了解一下
    2023-11-11
  • react中的forwardRef 和memo的区别解析

    react中的forwardRef 和memo的区别解析

    forwardRef和memo是React中用于性能优化和组件复用的两个高阶函数,本文给大家介绍react中的forwardRef 和memo的区别及适用场景,感兴趣的朋友跟随小编一起看看吧
    2023-10-10
  • react-redux及redux状态管理工具使用详解

    react-redux及redux状态管理工具使用详解

    Redux是为javascript应用程序提供一个状态管理工具集中的管理react中多个组件的状态redux是专门作状态管理的js库(不是react插件库可以用在其他js框架中例如vue,但是基本用在react中),这篇文章主要介绍了react-redux及redux状态管理工具使用详解,需要的朋友可以参考下
    2023-01-01
  • 实例讲解React 组件生命周期

    实例讲解React 组件生命周期

    这篇文章主要介绍了React 组件生命周期的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • React 中的重新渲染实现

    React 中的重新渲染实现

    本文主要介绍了React 中的重新渲染实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • react如何向数组中追加值

    react如何向数组中追加值

    这篇文章主要介绍了react如何向数组中追加值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • React Flux与Redux设计及使用原理

    React Flux与Redux设计及使用原理

    这篇文章主要介绍了React Flux与Redux设计及使用,Redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树(state对象)保存这一整个应用的状态,这个对象不能直接被改变
    2023-03-03
  • React Native使用Modal自定义分享界面的示例代码

    React Native使用Modal自定义分享界面的示例代码

    本篇文章主要介绍了React Native使用Modal自定义分享界面的示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 详解React 和 Redux的关系

    详解React 和 Redux的关系

    这篇文章主要为大家介绍了React 和 Redux的关系,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • react 中 mobx的使用案例详解

    react 中 mobx的使用案例详解

    这篇文章主要介绍了react 中 mobx的使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04

最新评论