Step 25: Rich Text Editor

We are going to use Mantine UI's Rich Text Editor. Let's add it as a dependency to our application:

yarn add @mantine/rte

Now we are going to update the Edit.jsx:

  • Add RichTextEditor from @mantine/rte instead of Textarea from @mantine/core.

  • Take our the <Textarea /> component and instead add the following:

    <RichTextEditor id="rte" defaultValue={"Your note's text"} value={text} onChange={setText} />
  • Finally, delete handleTextChange function as you don't need it anymore!

Here is the updated Edit.jsx
import { Button, Container, Group, Stack } from "@mantine/core"; import { TextInput } from "@mantine/core"; import { useEffect, useState } from "react"; import PropTypes from "prop-types"; import { useNavigate, useLocation } from "react-router-dom"; import { RichTextEditor } from "@mantine/rte"; function Edit(props) { const { edit, remove } = props; const navigate = useNavigate(); const location = useLocation(); const [id, setId] = useState(""); const [title, setTitle] = useState(""); const [text, setText] = useState(""); const [mode, setMode] = useState(""); useEffect(() => { if (location.state === null) { navigate("/", { replace: true }); } else { location.state.id !== id && setId(location.state.id); location.state.title !== title && setTitle(location.state.title); location.state.text !== text && setText(location.state.text); location.state.mode !== mode && setMode(location.state.mode); } }, [location.state]); const handleTitleChange = (event) => { setTitle(event.target.value); }; const handleSave = () => { edit(id, title, text); navigate("/", { replace: true }); }; const handleCancel = () => { if (mode === "remove-on-cancel") { remove(id); } navigate("/", { replace: true }); }; return ( <Container> <Stack spacing="lg"> <TextInput placeholder="Your note's title" label="Title" withAsterisk value={title} onChange={handleTitleChange} /> <RichTextEditor id="rte" defaultValue={"Your note's text"} value={text} onChange={setText} /> <Group position="center" spacing="xl" grow> <Button variant="subtle" onClick={handleCancel}> Cancel </Button> <Button variant="default" onClick={handleSave}> Save </Button> </Group> </Stack> </Container> ); } export default Edit; Edit.propTypes = { edit: PropTypes.func.isRequired, remove: PropTypes.func.isRequired, };

Next, we are going to update the components/Note.jsx file as follows:

- <Accordion.Panel>{note.text}</Accordion.Panel> + <Accordion.Panel> + <div dangerouslySetInnerHTML={{ __html: note.text }}></div> + </Accordion.Panel>

The dangerouslySetInnerHTML allows you to insert note.text as an HTML inside <Accordion.Panel> instead of a string. We need this since the rich text editor saves the note text as an HTML.

Run the app and observe how it works now.