skip to Main Content

I’m working on a small React project where I have two boxes: one for input and another for output. I want the input text to be displayed as rendered HTML in the output box. Essentially, I’m looking for the reverse of dangerouslySetInnerHTML.

Here’s what I’ve tried so far, but it’s not giving me the desired result:

import React, { useState, useEffect } from "react";
import "./InputOutput.css";

const InputOutput = () => {
  const [inputValue, setInputValue] = useState("");
  const [outputValue, setOutputValue] = useState("");

  useEffect(() => {
    const paragraphs = inputValue.split("n").map((p) => p.trim());
    const htmlParagraphs = paragraphs.map((p) => {
      if (!p) return "<p>&nbsp;</p>";
      return `<p>${p.replace(/ /g, "&nbsp;")}</p>`;
    });
    setOutputValue(htmlParagraphs.join(""));
  }, [inputValue]);

  return (
    <div className="container">
      <div className="input-box">
        <h2>Text</h2>
        <textarea
          placeholder="Type here"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
        />
      </div>
      <div className="output-box">
        <h2>HTML</h2>
        <div>{outputValue}</div>
      </div>
    </div>
  );
};

export default InputOutput;

Input:

Hello all, my name is Alex

This is one empty lane

These are 2 empty lanes

Expected Output:

<p>Hello all, my name is Alex</p>
<p>&nbsp;</p>
<p>This is one empty lane</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>These are 2 empty lanes</p>

Any suggestions on how to achieve this?

Thanks!

Showed on the question

Should be similar to Convert plain string to html in react

2

Answers


  1. you can define outputValue as component.

    import React, { useState, useEffect } from "react";
    
    const InputOutput = () => {
      const [inputValue, setInputValue] = useState("");
      const [outputValue, setOutputValue] = useState(<></>);
    
      useEffect(() => {
        const paragraphs = inputValue.split("n").map((p) => p.trim());
        const htmlParagraphs = <>
        {
           paragraphs.map((p) => {
            if (!p) return <p>&nbsp;</p>;
            return <p>{p}</p>;
          })
        }
        </>
       
        setOutputValue(htmlParagraphs);
      }, [inputValue]);
    
      return (
        <div className="container">
          <div className="input-box">
            <h2>Text</h2>
            <textarea
              placeholder="Type here"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
            />
          </div>
          <div className="output-box">
            <h2>HTML</h2>
            <div>{outputValue}</div>
          </div>
        </div>
      );
    };
    
    export default InputOutput;
    
    Login or Signup to reply.
  2. This is my solution, with map operator.

    import React, { useState, useEffect } from 'react';
    import './style.css';
    
    const App = () => {
      const [inputValue, setInputValue] = useState('');
      const [outputValue, setOutputValue] = useState('');
    
      useEffect(() => {
        const paragraphs = inputValue.split('n').map((p) => p.trim());
        const htmlParagraphs = paragraphs;
        setOutputValue(htmlParagraphs);
      }, [inputValue]);
    
      return (
        <div className="container">
          <div className="input-box">
            <h2>Text</h2>
            <textarea
              placeholder="Type here"
              value={inputValue}
              onChange={(e) => setInputValue(e.target.value)}
            />
          </div>
          <div className="output-box">
            <h2>HTML</h2>
            {outputValue &&
              outputValue.map((element) => (element ? <p> {element}</p> : <br />))}
          </div>
        </div>
      );
    };
    
    export default App;
    

    stackblitz

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search