So I have a functional component which is a toolbar. Its parent is a Text editor. The toolbar has many child components which are buttons. On clicking one of these buttons, I want a modal to appear. The logic of useModal
. But the FormatToolbarModal
does not appear.
I have read that all the rendering of a component must be done by the top level custom component? But I am unsure where to go from there. I want this modal to be reusable as other options from the toolbar will use it.
index.jsx
ReactDOM.render(routes, document.getElementById("app"));
App.jsx
const App = () => {
return (
<TextEditor/>
)
}
TextEditor.jsx
const TextEditor = () => {
return(
<FormatToolbar>
<FormatToolbarBlock format="link" icon={link2} />
<FormatToolbarBlock format="image" icon={image} />
</FormatToolbar>
... Editor stuff
)
}
const FormatToolbarBlock = ({ format, icon }) => {
const editor = useSlate();
const {isShowing, toggle} = useModal();
return (
<FormatButton
onMouseDown={e => {
if(format === 'link'){
toggle(e);
<FormatToolbarModal <---- here is my issue
isShowing={isShowing}
hide={toggle}
/>
} else if {
...
}
}}
/>
)
}
UseModal.jsx
const useModal = () => {
const [isShowing, setIsShowing] = useState(false);
function toggle() {
setIsShowing(!isShowing);
}
return {
isShowing,
toggle,
}
};
export default useModal;
FormatToolbarModal.jsx
const FormatToolbarModal = ({ isShowing, hide }) => isShowing ? ReactDOM.createPortal(
<React.Fragment>
<p>I am a modal</p>
</React.Fragment>, document.body
): null;
export default FormatToolbarModal;
Hopefully from this, you can see my issue clearer. Im new to React and hooks, so any advice is appreciated.
Thanks!
You're calling the function, but not passing the resulting JSX elements to anything that will render them. Think of the bootstrapping operation you use with the top-level component, where you pass the result into ReactDOM.render
or similar. That's what puts it on the page. You need to do the same thing with the result of calling your modal function.
You have a couple of options:
You might do it by having a flag that your function sets, and then conditionally rendering the modal within another component.
You might render it as (in?) a portal .
React 101.
React naming convention: Component names should follow pascal-case.
eg: from your code showModal should be ShowModal.
also your code is not sufficient to understand the structure(how and where these components are being rendered). what i'm saying is there are many other possible ways this could go south, but this alone could make this bug.
Okay so as I suspect and as TJ Crowder mentioned. My FormatButton
did not know how to render such a component. I moved the component like so, and wrapped it in a fragment. Now everything works.
For anyone having the same issue. Check out react portals. Also, this link helped: https://levelup.gitconnected.com/create-a-modal-with-react-hooks-357c8aae7c3f
TextEditor.jsx
const FormatToolbarBlock = ({ format, icon }) => {
const editor = useSlate();
const {isShowing, toggle} = useModal();
return (
<>
<FormatButton
onMouseDown={e => {
if(format === 'link'){
toggle(e);
} else if {
...
}
}}
/>
<FormatToolbarModal
isShowing={isShowing}
hide={toggle}
/>
</>
)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.