I have a number of strings with this format:
'The model of that car is [assignment: any car model] and it has [assignment: any number] horsepower'
I want to display this string in my UI and replace every occurrence of [custom: text] with a textbox. My CustomComponent
implements a textbox with a placeholder. I want the placeholder to be the text that comes between '[custom:' and the closing squared bracket.
I'm using reactStringReplace in order to replace string patterns with react components. The main problem is that reactStringReplace will replace every matching occurrence at the same time. Even if I match only the first occurrence, this will result in multiple checkboxes with the same placeholder.
I even tried to match only one occurrence removing '/g' at the end of the regex but still all occurrences are replaced
This is my code:
const reactStringReplace = require('react-string-replace');
const description = 'The model of that car is [custom: any car model] and it has [custom: any number] horsepower'
function formatString(input){
const regex = /\[assignment: (.*?)\]/g;
const regex_assignment = /\[assignment: (.*?)\]/;
let formattedString = input;
let match;
let placeholder;
let newString = input;
while ((match = regex.exec(input)) !== null) {
placeholder = match[1];
newString = reactStringReplace(newString,regex_assignment, ()=> (<CustomComponent placeholder={placeholder}/>))
}
return(newString);
}
return (
<div class = 'description'>
<div>{formatString(description)}</div>
</div>
);
The return value of reactStringReplace
is an array, not a string (and it has to be, to do its job). But you're treating it as a string.
You don't need to have the loop in your code, that's one of the things reactStringReplace
does for you, as they shown in the "More realistic example" section. So it's much simpler (I changed the regular expression to use custom
rather than assignment
since that's what's in the description
string):
function formatString(input) {
return reactStringReplace(input, /\[custom: (.*?)\]/g, (match, i) => (
<CustomComponent key={i} placeholder={match} />
));
}
(That's using the index for key
, which is usually an anti-pattern [see the Pitfall in this section of the React documentation], but I think choosing the right key is outside the scope of the question.)
Live Example:
const reactStringReplace = module.exports;
function formatString(input) {
return reactStringReplace(input, /\[custom: (.*?)\]/g, (match, i) => (
<CustomComponent key={i} placeholder={match} />
));
}
// Stand-in for CustomComponent
function CustomComponent({ placeholder }) {
return <span className="placeholder">{placeholder}</span>;
}
function Example() {
const description =
"The model of that car is [custom: any car model] and it has [custom: any number] horsepower";
return (
<div className="description">
<div>{formatString(description)}</div>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
.placeholder {
color: blue;
font-weight: bold;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<script>
const module = {};
</script>
<script src="https://unpkg.com/[email protected]/index.js"></script>