Search code examples
reactjsquillreact-quill

Render/Add quill editor on click of a button in react


I am stuck on this for a day now. Have read multiple answers but could not find anything.

My task is simple, I have a page where a user can answer a question.

  • The page will have two editors open(by default). (Found this in a react-quill GitHub discussion).

  • There will be an 'Add step' button which will, of course, add another quill editor below and the user can add as many steps as he/she likes.

  • The editors will have a 'Delete' button alongside it to delete the editors, except for the first two editors.

Now, I want to store the said steps separately in my DB as well, but the onClick on the editor does not have e.target, instead, it just gives the HTML value. Therefore, how can I add editors onClick and separate the value from the multiple editors?

Any direction or hint towards the solution would be appreciated. Thanks.


Solution

  • You can have separate values by using Array of Objects.

    It can be done by having two separate components,

    1. One for RichText Editor,
    2. A main component that has a state (Array of Objects)

    I used react-quill library for text editor and react-bootstrap for styling in the following code. You can replace one or both of them of your choice

    Create two components:

     - App.js // Main component
     - ReactQuill.js // Editor component 
    

    ReactQuill.js

        import React from "react";
        import ReactQuill from "react-quill";
        
        import "react-quill/dist/quill.snow.css";
        
        class ReactQuillEditor extends React.Component {
          render() {
            const { response, handleChange } = this.props;
            return (
              <ReactQuill
                style={{ marginTop: "4px" }}
                value={response}
                onChange={handleChange}
              />
            );
          }
        }
        
        export default ReactQuillEditor;
    

    App.js

    import { useState } from "react";
    import { Button } from "react-bootstrap";
    
    // Editor Component
    import Editor from "./components/ReactQuill";
    
    export default function App() {
      const [steps, setStep] = useState([
        {
          step: 1,
          response: ""
        },
        {
          step: 2,
          response: ""
        }
      ]); // For Default Two Inputs
    
      const handleChange = (value, index) => {
    
        // Updates, Remove and Replaces an object at index n
        const steptoReplace = steps[index];
        steptoReplace.response = value;
    
        steps.splice(index, 1);
        steps.splice(index, 0, steptoReplace);
    
        setStep(steps);
      };
    
     // Adds an empty entry
      const addStep = () => {
        setStep([
          ...steps,
          {
            step: steps.length + 1,
            response: ""
          }
        ]);
      };
    
      const reduceStep = () => {
        // To have Two text editor always
        if (steps.length > 2) {
          steps.pop();
          setStep([...steps]);
        }
      };
    
      const submit = () => {
        // You will have an Array of Objects of all steps
        console.log("steps", steps);
      };
    
      return (
        <div className="container">
          <h1>Multiple React Quill</h1>
          <div className="mt-4">
            {steps.map((step, index) => (
              <div key={index}>
                Step {index + 1}
                <Editor
                  response={step.response}
                  handleChange={(value) => handleChange(value, index)}
                />
              </div>
            ))}
    
            <div className="d-flex mt-4  justify-content-between">
              <Button onClick={addStep}>Add Step </Button>
              <Button onClick={reduceStep}>Remove Step</Button>
            </div>
    
            <Button className="mt-4" onClick={() => submit()}>
              Submit
            </Button>
          </div>
        </div>
      );
    }