Replace part of string with tag in JSX

前端 未结 12 1234
被撕碎了的回忆
被撕碎了的回忆 2020-12-16 09:39

I\'m trying to replace parts of a string with JSX tags, like so:

render: function() {
    result = this.props.text.replace(\":\",
相关标签:
12条回答
  • 2020-12-16 09:57

    I have come to following simple solution that does not include third party library or regex, maybe it can still help someone.

    Mainly just use .replace() to replace string with regular html written as string, like:

    text.replace('string-to-replace', '<span class="something"></span>')
    

    And then render it using dangerouslySetInnerHTML inside an element.

    Full example:

    const textToRepace = 'Insert :' // we will replace : with div spacer
    const content = textToRepace.replace(':', '<div class="spacer"></div>') : ''
    
    // then in rendering just use dangerouslySetInnerHTML
    render() {
        return(
            <div dangerouslySetInnerHTML={{
                __html: content
            }} />
        )
    }
    
    0 讨论(0)
  • 2020-12-16 09:58

    Example with hooks:

    import React, { useEffect, useState, useRef } from 'react'
    
    export function Highlight({ value, highlightText }) {
      const [result, resultSet] = useState(wrap())
    
      const isFirstRun = useRef(true) 
    
      function wrap() {
        let reg = new RegExp('(' + highlightText + ')', 'gi')
        let parts = value.split(reg)
    
        for (let i = 1; i < parts.length; i += 2) {
          parts[i] = (
            <span className='highlight' key={i}>
              {parts[i]}
            </span>
          )
        }
        return <div>{parts}</div>
      }
    
      useEffect(() => {
        //skip first run
        if (isFirstRun.current) {
          isFirstRun.current = false
          return
        }
        resultSet(wrap())
      }, [value, highlightText])
    
      return result
    }
    
    0 讨论(0)
  • 2020-12-16 10:11

    When you pass a JSX element to replace() as the second argument, that element is converted to a string because replace() expects a string as a second argument. What you need to do is convert your string to an array of strings and JSX elements. So your result variable should contain something like ['Lorem ', <div className="spacer"></div>, ' ipsum'].

    Something like this:

    function flatMap(array, fn) {
      var result = [];
      for (var i = 0; i < array.length; i++) {
        var mapping = fn(array[i]);
        result = result.concat(mapping);
      }
      return result;
    }
    
    var Comp = React.createClass({
      render: function () {
        var result = 'Lorem : ipsum';
        result = flatMap(result.split(':'), function (part) {
          return [part, <div>spacer</div>];
        });
        // Remove the last spacer
        result.pop();
        return (
          <div>        
            {result}
          </div>
        );
      }
    });
    
    0 讨论(0)
  • 2020-12-16 10:13

    Nothing around WEB globe worked for me exept this solution - https://www.npmjs.com/package/regexify-string

    Working with React, strings and doesn't have any additional dependecies

    regexifyString({
        pattern: /\[.*?\]/gim,
        decorator: (match, index) => {
            return (
                <Link
                    to={SOME_ROUTE}
                    onClick={onClick}
                >
                    {match}
                </Link>
            );
        },
        input: 'Some text with [link]',
    });
    
    0 讨论(0)
  • 2020-12-16 10:15

    i think this is the most light perfect solution:

    render() {
        const searchValue = "an";
        const searchWordRegex = new RegExp(searchValue, "gi");
        const text =
          "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text";
        return (
          <div>
            {text.split(searchWordRegex).length > 1
              ? text.split(searchWordRegex).map((chunk, index) => {
                  if (chunk !== "") {
                    return index === 0 &&
                      ! new RegExp("^" + searchValue, "gi").test(text) ? (
                      chunk
                    ) : (
                      <span key={index}>
                        <span
                          className="highlight"
                          style={{
                            fontWeight: "bold"
                          }}
                        >
                          {searchValue.charAt(0).toUpperCase() +
                            searchValue.slice(1)}
                        </span>
                        {chunk}
                      </span>
                    );
                  } else {
                    return null;
                  }
                })
              : text}
          </div>
        );
      }
    

    and here is a working example

    0 讨论(0)
  • 2020-12-16 10:19

    The following should also work (assumes ES6), The only nuance is that the text is actually wrapped inside a DIV element and not preceded by it, assuming you are going to use CSS for the actual spacing this shouldn't be a problem.

    const result = this.props.text.split(':').map(t => {
      return <div className='textItem'>{t}</div>;
    });
    
    0 讨论(0)
提交回复
热议问题