3

In this code snippet below I am trying to get every number that is typed and a string input to be subscribed (as for example in the H2O water formula)

const Reagents = (props) => {
return <div>
    <h1>Reagentes</h1>
    {props.reagent && props.reagent.map((param, i) =>
        <p key={i}>
            {param.reagent.replace(/(\d+)/g, '$1'.sub())}
        </p>)}
</div>

when i have H2O input it returns

H<sub>2</sub>O
  • Yes that's what `.sub()` does. What exactly is the problem? – Pointy Oct 31 '18 at 15:08
  • I want to return a indeed subscritpt number in my browser. – Felipe Domingues Oct 31 '18 at 15:09
  • 1
    If the problem is that React is escaping the content, I think you have to use [dangerouslySetInnerHtml](https://stackoverflow.com/questions/34231902/is-there-some-way-to-avoid-html-escaping-of-text-children-when-calling-react-cre). – Pointy Oct 31 '18 at 15:14

2 Answers2

3

You can write a tokenizer that splits the input string into letters and digits, and wraps the digit parts in <sub> elements.

const tokenize = (formula) => formula
  .split(/(\d+)/)
  .map((token, idx) => 
    idx % 2
      ? <sub key={idx}>{token}</sub>
      : token
    )

const Formula = ({children}) => (
  <code>{tokenize(children)}</code>
)

const App = () => (
  <div>
    <p>Water is <Formula>H2O</Formula></p>
    <p>Ethanol is <Formula>C2H5OH</Formula></p>
  </div>
)

ReactDOM.render(<App />, document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id=root />
Håken Lid
  • 22,318
  • 9
  • 52
  • 67
0

You can accomplish this with dangerouslySetInnerHTML, but do so with caution. Perhaps you have a component like this:

function Subscriptify({value}) {
    const innerHTML = { __html: value.replace(/(\d+)/g, '$1'.sub()) }
    return (
        <p dangerouslySetInnerHTML={innerHTML} />
    )
}

Then pass it the reagent.

SeanMcP
  • 293
  • 6
  • 19