不错的莫达尔
这是一种小而零的依赖性用途,可以自然地管理反应模式. 它利用上下文在全球持续保持模式状态,以便你能够很容易地通过模式成分或id来显示/隐藏一种模式.
您也可以在 eBay科技博客。 。 。 .
例如,您可以使用下面的代码在任何地方显示一个模式:
import NiceModal from '@ebay/nice-modal-react';
import MyModal from './MyModal';
//...
NiceModal.show(MyModal, { someProp: 'hello' }).then(() => {
// do something if the task in the modal finished.
});
//...
或者你可以用一个ID来注册模式,这样你不需要导入模式组件来使用:
import NiceModal from '@ebay/nice-modal-react';
import MyModal from './MyModal';
NiceModal.register('my-modal', MyModal);
// you can use the string id to show/hide the modal anywhere
NiceModal.show('my-modal', { someProp: 'hello' }).then(() => {
// do something if the task in the modal finished.
});
//...
页:1数字 : @ebay/nice-modal-react 不是一个反应模式组件,但应该与UI 库等其他模式/对话框一起使用 材料界面, (中文(简体) ), 蚂蚁. 设计, (中文(简体) ), 启动陷阱反应等 (中文(简体) ).
实例
您可以在 : https://ebay.github.io/nice-module-resact 互联网档案馆的存檔,存档日期2013-12-22
关键特性
- 零依赖和小:~2kb gzip后.
- 无所控制. 您可以在模式组件中关闭模式本身 .
- 解脱相. 无需导入模式组件即可使用. Modals可以通过id管理.
- 您模式组件的代码如果是隐形的,则不执行 .
- 它不会打破显示/隐藏模式的过渡.
- 承诺基于。 除了使用道具从母元件中与模式进行交互外,通过承诺也可以更容易地实现.
- 容易与任何UI库集成.
动机
在React中使用模式有点让人沮丧. 如果您需要执行以下 UI :
该对话框用于创建 JIRA 票. 它可以从许多地方显示,从头到上下文菜单,到列表页面. 传统上,我们申报了带有JSX标签的模式组件。 但问题就变成了“我们应该在哪里申报标签?”
最常见的选择是,无论它在哪里使用,都予以宣布。 但使用模式来宣示,不仅涉及JSX标签,也涉及维持模式状态,如能见度,集装箱组件中的参数。 逐一宣布意味着管理着各地的国家. 令人沮丧.
另一种选择将其置于Root组件中,例如:
const Root = () => {
const [visible, setVisible] = useState(false);
// other logic ...
return (
<>
<Main />
<NewTicketModal visible={visible} />
</>
);
}
然而,当您在根组件中声明模式时,还存在一些问题:
- 不可伸缩. 在根构件中保持模式状态是不合理的. 当您需要更多模式时, 您需要保持许多状态, 特别是您需要为模式保持参数 .
- 很难从儿童成分中显示或隐藏模式. 当你在一个组件中保持状态时,你需要通过
setVisible到需要展示或隐藏模式的地方。 事情太复杂了.
不幸的是,大多数使用模式的例子只是遵循了这种做法,在React中管理模式时造成了这样的混乱.
我认为,你必须曾经遇到这样的情景,原来你只需要在点击按钮时显示一个模式,然后当要求发生变化时,你需要从另一个地方打开同一个模式。 那你必须重构你的代码 重新考虑在哪里宣布模式。 造成这种烦恼的根源仅仅是因为我们不了解一种模式的本质.
在反应中重新思考 Modal 使用模式
根据 维基百科,一种模式可以描述为:
用于阻止用户与您的应用程序互动直到关闭窗口的窗口.
从定义中我们可以得出一个结论:一种模式是一个全球观点,它不一定与特定的上下文相关.
这与单页UI应用程序中的页面概念非常相近. 模式的能见度/状态应在全球范围内加以管理,因为从UI的角度来看,模式可以在任何页面/组件之上显示。 模式和页面的唯一区别是:一种模式允许您不离开当前页面去完成一些单独的任务.
对于页面管理,我们已经有像React Router这样的路由器框架,它帮助通过URL导航到一页. 实际上,您可以认为URL是一页的全球ID. 所以,同样,如果你给一个模式分配一个uniq id,然后由id显示/隐藏它呢? 我们就是这么设计的 Nice Modal.
然而,NiceModal除了使用id外,还允许直接使用模式组件来管理.
使用量
安装
# with yarn
yarn add @ebay/nice-modal-react
# or with npm
npm install @ebay/nice-modal-react
创建您的模块组件
使用 NiceModal 可以很容易地创建单独的模式组件 。 这和你创造一个正常的组件一样 但用高音量来包装它 NiceModal.create。例如,下面的代码显示如何创建对话框 蚂蚁. 设计数字 :
import { Modal } from 'antd';
import NiceModal, { useModal } from '@ebay/nice-modal-react';
export default NiceModal.create(({ name }) => {
// Use a hook to manage the modal state
const modal = useModal();
return (
<Modal
title="Hello Antd"
onOk={() => modal.hide()}
visible={modal.visible}
onCancel={() => modal.hide()}
afterClose={() => modal.remove()}
>
Hello {name}!
</Modal>
);
});
从代码来看,我们可以看到:
- 模式不受控制。 您可以将您的模式隐藏在组件中, 不管它显示在哪里 .
- 由
NiceModal.create确保组件在可见之前不会被执行. - 你可以打电话
modal.remove从 React 组件树去除您的模式组件到保留过渡.
接下来,让我们看看如何使用模式.
使用您的模块组件
有非常灵活的API供您管理模式. 见下文导言.
嵌入您的应用程序 NiceModal.Provider数字 :
由于我们将在全球管理模式状态,第一件事就是将您的应用程序嵌入NiceModal供应商,例如:
import NiceModal from '@ebay/nice-modal-react';
ReactDOM.render(
<React.StrictMode>
<NiceModal.Provider>
<App />
</NiceModal.Provider>
</React.StrictMode>,
document.getElementById('root'),
);
提供者会使用React上下文来保持所有模式状态.
按组件使用模式
您可以通过组件本身控制一个很好的模式 .
import NiceModal from '@ebay/nice-modal-react';
import MyAntdModal from './my-antd-modal'; // created by above code
function App() {
const showAntdModal = () => {
// Show a modal with arguments passed to the component as props
NiceModal.show(MyAntdModal, { name: 'Nate' })
};
return (
<div className="app">
<h1>Nice Modal Examples</h1>
<div className="demo-buttons">
<button onClick={showAntdModal}>Antd Modal</button>
</div>
</div>
);
}
通过 id 使用模式
您也可以通过 id 控制一个很好的模式 :
import NiceModal from '@ebay/nice-modal-react';
import MyAntdModal from './my-antd-modal'; // created by above code
// If use by id, need to register the modal component.
// Normally you create a modals.js file in your project
// and register all modals there.
NiceModal.register('my-antd-modal', MyAntdModal);
function App() {
const showAntdModal = () => {
// Show a modal with arguments passed to the component as props
NiceModal.show('my-antd-modal', { name: 'Nate' })
};
return (
<div className="app">
<h1>Nice Modal Examples</h1>
<div className="demo-buttons">
<button onClick={showAntdModal}>Antd Modal</button>
</div>
</div>
);
}
用钩子模式
这个 useModal 钩子不仅可以在模式组件内使用,也可以通过传递方式代号/组件来使用:
import NiceModal, { useModal } from '@ebay/nice-modal-react';
import MyAntdModal from './my-antd-modal'; // created by above code
NiceModal.register('my-antd-modal', MyAntdModal);
//...
// if use with id, need to register it first
const modal = useModal('my-antd-modal');
// or if with component, no need to register
const modal = useModal(MyAntdModal);
//...
modal.show({ name: 'Nate' }); // show the modal
modal.hide(); // hide the modal
//...
宣布您的模式而不是 register
你创造的优雅模式组件也可以被JSX用作普通组件,那么你不需要注册. 例如:
import NiceModal, { useModal } from '@ebay/nice-modal-react';
import MyAntdModal from './my-antd-modal'; // created by above code
function App() {
const showAntdModal = () => {
// Show a modal with arguments passed to the component as props
NiceModal.show('my-antd-modal')
};
return (
<div className="app">
<h1>Nice Modal Examples</h1>
<div className="demo-buttons">
<button onClick={showAntdModal}>Antd Modal</button>
</div>
<MyAntdModal id="my-antd-modal" name="Nate" />
</div>
);
}
有了这个方法,你可以得到优雅:
- 继承 在某些组件节点下的模式组件中发生上下文 .
- 通过道具将参数传递到模式组件.
注:如果以 id 方式显示组件,但模式不宣布或登记。 只会在Dev控制台发出警告.
使用承诺 API
除了使用道具从母元件中与模式进行交互外,通过承诺也可以更容易地实现. 例如,我们有一个用户列表页面,其中包含一个添加用户按钮,以显示一个对话框来添加用户. 在用户被添加后,列表应该刷新自己以反映变化,然后我们可以使用下面的代码:
NiceModal.show(AddUserModal)
.then(() => {
// When call modal.resolve(payload) in the modal component
// it will resolve the promise returned by `show` method.
// fetchUsers will call the rest API and update the list
fetchUsers()
})
.catch(err=> {
// if modal.reject(new Error('something went wrong')), it will reject the promise
});
您可以在代码和框上看到现场实例.
与 Redux 合并
尽管没有必要,但可以集成Redux来管理好模式状态. 然后可以使用Redux dev工具来跟踪/调试模式的状态变化. 这是如何做到的:
// First combine the reducer
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
import NiceModal from '@ebay/nice-modal-react';
import { Button } from 'antd';
import { MyAntdModal } from './MyAntdModal';
import logger from 'redux-logger';
const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
const enhancer = composeEnhancers(applyMiddleware(logger));
const store = createStore(
combineReducers({
modals: NiceModal.reducer,
// other reducers...
}),
enhancer,
);
// Passing Redux state to the nice modal provider
const ModalsProvider = ({ children }) => {
const modals = useSelector((s) => s.modals);
const dispatch = useDispatch();
return (
<NiceModal.Provider modals={modals} dispatch={dispatch}>
{children}
</NiceModal.Provider>
);
};
export default function ReduxProvider({ children }) {
return (
<Provider store={store}>
<ModalsProvider>{children}</ModalsProvider>
</Provider>
);
}
使用任何 UI 库
NiceModal提供生命囊方法来管理模式状态. 您可以使用模式处理器返回 useModal 钩子将任何类似组件的模式绑入状态。 以下是您将使用的典型状态和方法:
- 模式. 可见:一种模式的能见度.
- 模式. hide:将隐藏模式,即更改
modal.visible以假相报. - 模式. 移动: 从树上去除模式组件, 以便您模式的代码在不可见时不被执行 。 通常在模式的过渡后称为这种方法.
- 模式. 保持流动 如果您不想在某些情况下从树上移除模式, 您可以决定是否调用
modal.remove基于数值keepMounted。 。 。 .
基于这些属性/方法,您可以轻松地使用由任何UI库提供的任何模式式组件.
使用帮助方法
如你所见,我们使用类似下面的代码来管理模式状态:
//...
const modal = useModal();
return (
<Modal
visible={modal.visible}
title="Hello Antd"
onOk={() => modal.hide()}
onCancel={() => modal.hide()}
afterClose={() => modal.remove()}
>
Hello NiceModal!
</Modal>
);
//...
它的束缚 visible 属性 modal 处理器,和使用 modal.hide 来隐藏关闭按钮时的模式。 在接近过渡后,它呼唤 modal.remove 从多姆节点中删除模式.
对于每一个模式的实施,我们总是需要用人工方式进行这些约束。 因此,为了更容易使用,我们为3个受欢迎的UI库材料UI,Ant.Design和Bootstrap React提供了帮助方法.
import NiceModal, {
muiDialog,
muiDialogV5,
antdModal,
antdModalV5,
antdDrawer,
antdDrawerV5,
bootstrapDialog
} from '@ebay/nice-modal-react';
//...
const modal = useModal();
// For MUI
<Dialog {...muiDialog(modal)}>
// For MUI V5
<Dialog {...muiDialogV5(modal)}>
// For ant.design
<Modal {...antdModal(modal)}>
// For ant.design v4.23.0 or later
<Modal {...antdModalV5(modal)}>
// For antd drawer
<Drawer {...antdDrawer(modal)}>
// For antd drawer v4.23.0 or later
<Drawer {...antdDrawerV5(modal)}>
// For bootstrap dialog
<Dialog {...bootstrapDialog(modal)}>
这些帮助者将约束模式的共同行动来纠正组件的属性. 然而,您总是可以在帮助者财产之后推翻财产。 例如:
const handleSubmit = () => {
doSubmit().then(() => {
modal.hide();
});
}
<Modal {...antdModal(modal)} onOk={handleSubmit}>
举例来说 onOk 属性将覆盖来自 antdModal 帮手.
API 参考
https://ebay.github.io/nice-module-react/api/ 互联网档案馆的存檔,存档日期2013-12-02
测试
你可以用工具测试你漂亮的模式 @testing-library/react。 。 。 .
import NiceModal from '@ebay/nice-modal-react';
import { render, act, screen } from '@testing-library/react';
import { MyNiceModal } from '../MyNiceModal';
test('My nice modal works!', () => {
render(<NiceModal.Provider />
act(() => {
NiceModal.show(MyNiceModal);
});
expect(screen.getByRole('dialog')).toBeVisible();
});
贡献指南
# 1. Clone repo
git clone https://github.com/eBay/nice-modal-react.git
# 2. Install deps
cd nice-modal-react
yarn
# 3. Make local repo as linked
yarn link
# 4. Start dev server
yarn dev
# 5. Install examples deps
cd example
yarn
# 6. Use local linked lib
yarn link @ebay/nice-modal-react
# 7. Start examples dev server
yarn start
然后您可以访问 http://localhost: 3: 00 查看实例.
财务问题
我能用一种模式在组件树上找到背景吗?
对 要从组件树的上下文中获取数据,需要使用声明方式. 例如:
export default function AntdSample() {
return (
<>
<Button type="primary" onClick={() => NiceModal.show('my-antd-modal', { name: 'Nate' })}>
Show Modal
</Button>
<MyAntdModal id="my-antd-modal" {...otherProps} />
</>
);
}
看见更多 这里。 。 。 .
许可证
麻省理工学院