web-dev-qa-db-ja.com

JSXで文字列の一部をタグに置き換えます

次のように、文字列の一部をJSXタグに置き換えようとしています。

render: function() {
    result = this.props.text.replace(":",<div className="spacer"></div>);
    return (
         <div>        
             {result}
         <div>        
    );
}

ただし、this.props.textLorem : ipsum、結果は

<div>
    Lorem [object Object] ipsum.
</div>

これを解決する方法や、文字列の一部をJSXタグに置き換える別の方法はありますか?

19
Magnus Engdal

JSX要素を2番目の引数としてreplace()に渡すと、replace()は2番目の引数として文字列を予期するため、その要素は文字列に変換されます。必要なのは、文字列を文字列とJSX要素の配列に変換することです。したがって、result変数には['Lorem ', <div className="spacer"></div>, ' ipsum']

このようなもの:

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>
    );
  }
});
19
Anders Ekdahl

受け入れられた答えは2歳です。この問題のために #3368 が作成され、Reactで作業しているFacebookの従業員によって提供されたソリューションに基づいて react-string-replace が作成されました。

次に、react-string-replaceを使用して、問題を解決する方法を示します。

const reactStringReplace = require('react-string-replace');

const HighlightNumbers = React.createClass({
  render() {
    const content = 'Hey my number is 555:555:5555.';
    return (
      <span>
        {reactStringReplace(content, ':', (match, i) => (
          <div className="spacer"></div>
        ))}
      </span>
    );
  },
});
6
Matthew Barbara

以下も機能するはずです(ES6を想定)、唯一のニュアンスは、テキストが実際にDIV要素内にラップされ、その前にないことです。実際の間隔にCSSを使用する場合、これは問題になりません。

const result = this.props.text.split(':').map(t => { return <div className='textItem'>{t}</div>; });

5
Andy Polhill

いくつかの調査の結果、既存のライブラリは私の要件に合わないことがわかりました。だから、もちろん、私は自分で書いた:

https://github.com/EfogDev/react-process-string

使い方はとても簡単です。あなたの事例:

let result = processString({
    regex: /:/gim,
    fn: () => <div className="spacer"></div>
})(this.props.test);
1
Efog

より一般的なタスクがありました-すべての(英語)単語をカスタムタグでラップします。私の解決策:

class WrapWords extends React.Component {
  render() {
    const text = this.props.text;
    const isEnglishWord = /\b([-'a-z]+)\b/ig;
    const CustomWordTag = 'Word';

    const byWords = text.split(isEnglishWord);

    return (
    <div>
      {
        byWords.map(Word => {
          if (Word.match(isEnglishWord)) {
            return <CustomWordTag>{Word}</CustomWordTag>;
          }
          return Word;
        })
      }
    </div>
    );
    
  }
}

// Render it
ReactDOM.render(
  <WrapWords text="Argentina, were playing: England in the quarter-finals (the 1986 World Cup in Mexico). In the 52nd minute the Argentinian captain, Diego Maradona, scored a goal." />,
  document.getElementById("react")
);
<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="react"></div>
1
Londeren

フックの例:

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
RTW

Jsxのユーティリティ関数を作成しました。

const wrapTags = (text: string, regex: RegExp, className?: string) => {
  const textArray = text.split(regex);
  return textArray.map(str => {
    if (regex.test(str)) {
      return <span className={className}>{str}</span>;
    }
    return str;
  });
};

0
Tushar Tilwani

置換内で置換を行えるようにしたい場合(たとえば、URL内の検索語を強調表示するため)、作成したこのノードモジュールを確認してください- https://github.com/marcellosachs/react- string-replace-recursively

0
user1050268

私はサードパーティのライブラリや正規表現を含まないシンプルなソリューションに従うことになりました。おそらく誰かを助けることができます。

主に.replace()を使用して、次のように文字列を文字列として記述された通常のhtmlに置き換えます。

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

次に、要素内でdangerouslySetInnerHTMLを使用してレンダリングします。

完全な例:

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
Aleksej