次のように、文字列の一部をJSXタグに置き換えようとしています。
render: function() {
result = this.props.text.replace(":",<div className="spacer"></div>);
return (
<div>
{result}
<div>
);
}
ただし、this.props.text
はLorem : ipsum
、結果は
<div>
Lorem [object Object] ipsum.
</div>
これを解決する方法や、文字列の一部をJSXタグに置き換える別の方法はありますか?
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>
);
}
});
受け入れられた答えは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>
);
},
});
以下も機能するはずです(ES6を想定)、唯一のニュアンスは、テキストが実際にDIV要素内にラップされ、その前にないことです。実際の間隔にCSSを使用する場合、これは問題になりません。
const result = this.props.text.split(':').map(t => { return <div className='textItem'>{t}</div>; });
いくつかの調査の結果、既存のライブラリは私の要件に合わないことがわかりました。だから、もちろん、私は自分で書いた:
https://github.com/EfogDev/react-process-string
使い方はとても簡単です。あなたの事例:
let result = processString({
regex: /:/gim,
fn: () => <div className="spacer"></div>
})(this.props.test);
より一般的なタスクがありました-すべての(英語)単語をカスタムタグでラップします。私の解決策:
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>
フックの例:
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
}
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;
});
};
置換内で置換を行えるようにしたい場合(たとえば、URL内の検索語を強調表示するため)、作成したこのノードモジュールを確認してください- https://github.com/marcellosachs/react- string-replace-recursively
私はサードパーティのライブラリや正規表現を含まないシンプルなソリューションに従うことになりました。おそらく誰かを助けることができます。
主に.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
}} />
)
}