Reputation: 1
I have written a React component using MUI Modal, Popover, and Box inside my modal there is a <Box />
which contentEditable true what I am trying to do upon focusing on box open popover which will some options, and on blur close that popover. but as soon as I focused I got the error of infinite loop. I debug and found that it is happening because of a focus shift between popover and box.
This is my code
import React, { useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { ClickAwayListener } from '@mui/material';
import {
Modal,
Box,
IconButton,
Paper,
Popover,
ButtonGroup,
Button,
} from '@mui/material';
import {
Plus,
Bold,
AlignLeft,
AlignCenter,
AlignRight,
Type
} from 'lucide-react';
interface Editor {
id: string;
value: string;
}
interface ToolbarProps {
anchorEl: HTMLDivElement | null;
onClose: () => void;
onFormat: (command: string, value?: string) => void;
}
const Toolbar: React.FC<ToolbarProps> = ({ anchorEl, onClose, onFormat }) => {
return (
<Popover open={Boolean(anchorEl)} onClose={onClose}>
<ButtonGroup variant="outlined" size="small">
<IconButton onClick={() => onFormat("bold")}>
<Bold size={16} />
</IconButton>
<IconButton onClick={() => onFormat("fontSize", "2")}>
<Type size={14} />
</IconButton>
<IconButton onClick={() => onFormat("fontSize", "7")}>
<Type size={18} />
</IconButton>
<IconButton onClick={() => onFormat("justifyLeft")}>
<AlignLeft size={16} />
</IconButton>
<IconButton onClick={() => onFormat("justifyCenter")}>
<AlignCenter size={16} />
</IconButton>
<IconButton onClick={() => onFormat("justifyRight")}>
<AlignRight size={16} />
</IconButton>
</ButtonGroup>
</Popover>
);
};
export const TextEditor: React.FC = () => {
const [editors, setEditors] = useState<Editor[]>([]);
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>(null);
const [activeEditorId, setActiveEditorId] = useState<string | null>(null);
const handleAddEditor = () => {
const newEditor = {
id: uuidv4(),
value: '',
};
setEditors([...editors, newEditor]);
};
const handleEditorChange = (id: string, value: string) => {
setEditors(editors.map(editor =>
editor.id === id ? { ...editor, value } : editor
));
};
const handleEditorFocus = (event: React.FocusEvent<HTMLDivElement>, id: string) => {
setAnchorEl(event.currentTarget);
setActiveEditorId(id);
};
const handleEditorBlur = (event: React.FocusEvent<HTMLDivElement>) => {
setAnchorEl(null);
setActiveEditorId(null);
}
const handleFormat = (command: string, value?: string) => {
document.execCommand(command, false, value);
};
return (
<Modal
open={true}
aria-labelledby="text-editor-modal"
className="flex items-center justify-center"
>
<Box className="bg-white rounded-lg p-6 w-[600px] max-h-[80vh] overflow-y-auto">
<div className="flex justify-between items-center mb-4">
<h2 className="text-xl font-semibold">Text Editor</h2>
<IconButton onClick={handleAddEditor} color="primary">
<Plus />
</IconButton>
</div>
<div className="space-y-4">
{editors.map((editor) => (
<Box
key={editor.id}
contentEditable
onFocus={(e) => handleEditorFocus(e, editor.id)}
onBlur={handleEditorBlur}
onInput={(e) => handleEditorChange(editor.id, e.currentTarget.innerHTML)}
className="min-h-[100px] p-4 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
dangerouslySetInnerHTML={{ __html: editor.value }}
/>
))}
</div>
<Toolbar
anchorEl={anchorEl}
onClose={() => setAnchorEl(null)}
onFormat={handleFormat}
/>
</Box>
</Modal>
);
};
This is my getting in dev console:
[email protected]:26 The above error occurred in the <Transition2> component:
at Transition2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:13089:30)
at Fade2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:23588:17)
at Backdrop2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:23809:17)
at https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…ntainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:1691:50
at div
at https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…ntainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:1691:50
at Portal2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:19751:15)
at Modal2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:28248:17)
at https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…ntainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:1691:50
at Popover2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:36682:17)
at Toolbar (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentialless.webcontainer-api.io/src/components/TextEditor.tsx:35:20)
at div
at https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…ntainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:1691:50
at Box4 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…ntainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:7990:19)
at FocusTrap (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:27815:15)
at div
at https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…ntainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:1691:50
at Portal2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:19751:15)
at Modal2 (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentia…tainer-api.io/node_modules/.vite/deps/@mui_material.js?v=482cf364:28248:17)
at TextEditor (https://zp1v56uxy8rdx5ypatb0ockcb9tr6a-oci3--5173--c8c182a3.local-credentialless.webcontainer-api.io/src/components/TextEditor.tsx:104:33)
at div
at App
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
chunk-6VWAHX6D.js?v=15727a7e:19659 Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
at checkForNestedUpdates (chunk-6VWAHX6D.js?v=15727a7e:19659:19)
at scheduleUpdateOnFiber (chunk-6VWAHX6D.js?v=15727a7e:18533:11)
at Object.enqueueSetState (chunk-6VWAHX6D.js?v=15727a7e:13467:15)
at Component.setState (chunk-QJTFJ6OV.js?v=15727a7e:229:24)
at Transition2.safeSetState (@mui_material.js?v=482cf364:13246:10)
at Transition2.performEnter (@mui_material.js?v=482cf364:13198:10)
at Transition2.updateStatus (@mui_material.js?v=482cf364:13172:14)
at Transition2.componentDidUpdate (@mui_material.js?v=482cf364:13141:10)
at commitLayoutEffectOnFiber (chunk-6VWAHX6D.js?v=15727a7e:17053:36)
at commitLayoutMountEffects_complete (chunk-6VWAHX6D.js?v=15727a7e:17980:17)
checkForNestedUpdates @ chunk-6VWAHX6D.js?v=15727a7e:19659
scheduleUpdateOnFiber @ chunk-6VWAHX6D.js?v=15727a7e:18533
enqueueSetState @ chunk-6VWAHX6D.js?v=15727a7e:13467
Component.setState @ chunk-QJTFJ6OV.js?v=15727a7e:229
safeSetState @ @mui_material.js?v=482cf364:13246
performEnter @ @mui_material.js?v=482cf364:13198
updateStatus @ @mui_material.js?v=482cf364:13172
componentDidUpdate @ @mui_material.js?v=482cf364:13141
commitLayoutEffectOnFiber @ chunk-6VWAHX6D.js?v=15727a7e:17053
commitLayoutMountEffects_complete @ chunk-6VWAHX6D.js?v=15727a7e:17980
commitLayoutEffects_begin @ chunk-6VWAHX6D.js?v=15727a7e:17969
commitLayoutEffects @ chunk-6VWAHX6D.js?v=15727a7e:17920
commitRootImpl @ chunk-6VWAHX6D.js?v=15727a7e:19353
commitRoot @ chunk-6VWAHX6D.js?v=15727a7e:19277
performSyncWorkOnRoot @ chunk-6VWAHX6D.js?v=15727a7e:18895
flushSyncCallbacks @ chunk-6VWAHX6D.js?v=15727a7e:9119
(anonymous) @ chunk-6VWAHX6D.js?v=15727a7e:18627
Upvotes: 0
Views: 16