前言
前些日子在做项目的时候,需要封装一个toast
组件。我想起之前用过的库,只要在入口文件中引入就可以在全局中使用,还是很方便的,借这次机会也来实现一下。说起来也算是forwardref
、useimperativehanle
和usecontext
的实际使用。
- 第一种,使用
forwardref
和useimperativehanle
一个是像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
,它们通常一起使用,以便在父组件中暴露子组件的特定方法或属性。
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
用于访问组件树中某个层级上定义的 context
。context
提供了一种在组件之间共享值的方式,而不必通过组件树的每个层级显式传递 props
。
- 创建 context
首先,你需要创建一个 context
对象。这可以通过调用 react.createcontext
来完成。你还可以为默认值提供一个参数,如果 context
的 provider
没有在组件树中找到,将使用这个默认值。
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的资料请关注代码网其它相关文章!
发表评论