基于React編寫一個(gè)全局Toast的示例代碼
前言
前些日子在做項(xiàng)目的時(shí)候,需要封裝一個(gè)Toast組件。我想起之前用過的庫,只要在入口文件中引入就可以在全局中使用,還是很方便的,借這次機(jī)會(huì)也來實(shí)現(xiàn)一下。說起來也算是forwardRef、useImperativeHanle和useContext的實(shí)際使用。
- 第一種,使用
forwardRef和useImperativeHanle
一個(gè)是像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()都有提示。忘記什么庫了。
文中就用antd的message來模擬一下我們自己寫的Toast組件。
正文
我們先來了解一下forwardRef、useImperativeHanle和useContext的基本使用。
forwardRef 和 useImperativeHandle 的基本使用
forwardRef 和 useImperativeHandle,它們通常一起使用,以便在父組件中暴露子組件的特定方法或?qū)傩浴?/p>
forwardRef,它允許你將父組件的ref轉(zhuǎn)發(fā)到子組件中的某個(gè) DOM 節(jié)點(diǎn)或其他 React 組件。這樣,父組件就可以訪問子組件的引用,并直接操作它。
useImperativeHandle 是一個(gè)自定義 Hook,它允許你自定義通過 forwardRef 暴露給父組件的 ref 值。你可以指定哪些方法或屬性被暴露,而不是直接暴露整個(gè) DOM 節(jié)點(diǎn)或組件實(shí)例。
下面是一個(gè)簡單的例子
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>準(zhǔn)備中</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用于訪問組件樹中某個(gè)層級(jí)上定義的 Context。Context 提供了一種在組件之間共享值的方式,而不必通過組件樹的每個(gè)層級(jí)顯式傳遞 props。
- 創(chuàng)建 Context
首先,你需要?jiǎng)?chuàng)建一個(gè) Context 對象。這可以通過調(diào)用 React.createContext 來完成。你還可以為默認(rèn)值提供一個(gè)參數(shù),如果 Context 的 Provider 沒有在組件樹中找到,將使用這個(gè)默認(rèn)值。
import React from 'react';
const MyContext = React.createContext('defaultValue');
- 提供 Context
你需要在組件樹中的某個(gè)地方提供這個(gè) Context。這通常在組件的頂層完成,通過使用 MyContext.Provider組件,并傳遞一個(gè) 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 的當(dāng)前值
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>準(zhǔn)備中</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')
}}
>
點(diǎn)擊提示
</div>
</>
}
結(jié)尾
以上就是基于React編寫一個(gè)全局Toast的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于React編寫全局Toast的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react?diff?算法實(shí)現(xiàn)思路及原理解析
這篇文章主要介紹了react?diff?算法實(shí)現(xiàn)思路及原理解析,本節(jié)我們正式進(jìn)入基本面試必考的核心地帶?--?diff?算法,了解如何優(yōu)化和復(fù)用?dom?操作的,還有我們常見的?key?的作用,需要的朋友可以參考下2022-05-05
詳解前端路由實(shí)現(xiàn)與react-router使用姿勢
本篇文章主要介紹了詳解前端路由和react-router使用姿勢,詳細(xì)的介紹了react-router的用法,有興趣的可以了解一下2017-08-08
React高階組件優(yōu)化文件結(jié)構(gòu)流程詳解
高階組件就是接受一個(gè)組件作為參數(shù)并返回一個(gè)新組件(功能增強(qiáng)的組件)的函數(shù)。這里需要注意高階組件是一個(gè)函數(shù),并不是組件,這一點(diǎn)一定要注意,本文給大家分享React 高階組件HOC使用小結(jié),一起看看吧2023-01-01
react native實(shí)現(xiàn)監(jiān)控手勢上下拉動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了react native實(shí)現(xiàn)監(jiān)控手勢上下拉動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
Objects are not valid as a Rea
這篇文章主要為大家介紹了Objects are not valid as a React child報(bào)錯(cuò)解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
阿里低代碼框架lowcode-engine自定義設(shè)置器詳解
這篇文章主要為大家介紹了阿里低代碼框架lowcode-engine自定義設(shè)置器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
React+Electron快速創(chuàng)建并打包成桌面應(yīng)用的實(shí)例代碼
這篇文章主要介紹了React+Electron快速創(chuàng)建并打包成桌面應(yīng)用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12

