[英]Modal component does not render on a custom button component
I am trying to render a custom and dynamic modal on button clicks.我正在尝试在单击按钮时呈现自定义和动态模式。 For example, when a "Game" button is clicked, I would like a modal to render with specfics about the game and when a "Bank" button is clicked, I would like the modal to populate with specfics about a bank.
例如,当单击“游戏”按钮时,我希望使用有关游戏的规范来呈现模式,当单击“银行”按钮时,我希望模式中填充有关银行的规范。
First, when I add an onClick function to a custom button component, the modal does not render.首先,当我将 onClick function 添加到自定义按钮组件时,模态不会呈现。 However, when I put the onClick function on a regular button, the modal does render.
但是,当我将 onClick function 放在常规按钮上时,模式会呈现。 How can I simply add an onClick function on any component to render a dynamic modal?
如何在任何组件上简单地添加 onClick function 以呈现动态模态?
Second, I would like to populate each modal with differnet data.其次,我想用不同的数据填充每个模式。 For example, a "Game" button would populate the modal with a title of "Game" and so on.
例如,“游戏”按钮将使用标题“游戏”等填充模态框。 I'm using props to do this, but is that the best solution?
我正在使用道具来做到这一点,但这是最好的解决方案吗?
Here is the code I have so far, but it is broken when I add the onClick function to components.这是我到目前为止的代码,但是当我将 onClick function 添加到组件时它被破坏了。
// Navbar.js
import { ModalContext } from '../contexts/ModalContext'
function Navbar() {
const [showModal, updateShowModal] = React.useState(false)
const toggleModal = () => updateShowModal((state) => !state)
return(
<ModalContext.Provider value={{ showModal, toggleModal }}>
<Modal
title="Title"
canShow={showModal}
updateModalState={toggleModal}
/>
</ModalContext.Provider>
)
// does not render a modal
<Button
onClick={toggleModal}
type="navItem"
label="Game"
icon="windows"
/>
// render a modal
<button onClick={toggleModal}>Show Modal</button>
)
}
import { ModalContext } from '../contexts/ModalContext'
// Modal.js
const Modal = ({ title }) => {
return (
<ModalContext.Consumer>
{(context) => {
if (context.showModal) {
return (
<div style={modalStyles}>
<h1>{title}</h1>
<button onClick={context.toggleModal}>X</button>
</div>
)
}
return null
}}
</ModalContext.Consumer>
)
}
// modalContext.js
export const ModalContext = React.createContext()
// Button.js
function Button({ label, type = 'default', icon }) {
return (
<ButtonStyle buttonType={type}>
{setIcon(icon)}
{label}
</ButtonStyle>
)
}
I think the onClick
prop of the <Button>
component is not pointing to the onClick
of the actual HTML button
inside the component.我认为
<Button>
组件的onClick
道具没有指向组件内实际HTML button
的onClick
。 Could you please check that?你能检查一下吗? And if you think It's been set up in the right way, then can you share the code of the component?
如果你认为它已经以正确的方式设置,那么你可以分享组件的代码吗?
Yes, there's another way to do that.是的,还有另一种方法可以做到这一点。 And I think it's React Composition .
我认为它是React Composition 。 You can build the modal as the following:
您可以按以下方式构建模态:
<Modal
showModal={showModal}
updateModalState={toggleModal}
>
<div className="modal__header">{title}</div>
<div className="modal__body">{body}</div>
<div className="modal__footer">{footer}</div>
</Modal>
I think this pattern will give you more control over that component.我认为这种模式会让你更好地控制那个组件。
You are not passing the onClick
prop through to the styled button component.您没有将
onClick
道具传递给样式按钮组件。
Given style-component button:给定样式组件按钮:
const ButtonStyle = styled.button``;
The custom Button
component needs to pass all button props on to the ButtonStyle
component.自定义
Button
组件需要将所有按钮道具传递给ButtonStyle
组件。
// Button.js
function Button({ label, type='default', icon, onClick }) {
return (
<ButtonStyle buttonType={type} onClick={onClick}>
{setIcon(icon)}
{label}
</ButtonStyle>
)
}
If there are other button props then you can use the Spread syntax to collect them into a single object that can then be spread into the ButtonStyle
component.如果还有其他按钮道具,那么您可以使用 Spread 语法将它们收集到单个 object 中,然后可以将其传播到
ButtonStyle
组件中。
// Button.js
function Button({ label, type = 'default', icon, ...props }) {
return (
<ButtonStyle buttonType={type} {...props}>
{setIcon(icon)}
{label}
</ButtonStyle>
)
}
For the second issue I suggest encapsulating the open/close/title state entirely in the modal context provider, along with the Modal
component.对于第二个问题,我建议将打开/关闭/标题 state 与
Modal
组件一起完全封装在模态上下文提供程序中。
Here's an example implementation:这是一个示例实现:
const ModalContext = React.createContext({
openModal: () => {},
});
const Modal = ({ title, onClose}) => (
<>
<h1>{title}</h1>
<button onClick={onClose}>X</button>
</>
)
const ModalProvider = ({ children }) => {
const [showModal, setShowModal] = React.useState(false);
const [title, setTitle] = React.useState('');
const openModal = (title) => {
setShowModal(true);
setTitle(title);
}
const closeModal = () => setShowModal(false);
return (
<ModalContext.Provider value={{ openModal }}>
{children}
{showModal && <Modal title={title} onClose={closeModal} />}
</ModalContext.Provider>
)
}
Example consumer to set/open a modal:示例消费者设置/打开模式:
const OpenModalButton = ({ children }) => {
const { openModal } = useContext(ModalContext);
return <button onClick={() => openModal(children)}>{children}</button>
}
Example usage:示例用法:
function App() {
return (
<ModalProvider>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<OpenModalButton>Modal A</OpenModalButton>
<OpenModalButton>Modal B</OpenModalButton>
</div>
</ModalProvider>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.