Рабочий пример (jsfiddle)
Основная логика находится в компоненте SearchResults:
class SearchResults extends React.PureComponent {
render() {
const { target, results } = this.props
return (
<div className="SearchResults">
{_
.chain(results)
.map(word => word.split(target))
.map(parts => _.reduce(
parts,
(res, part) => res.length > 0
? [ ...res, <span className="highlight">{target}</span>, part ]
: [ part ]
,
[]
))
.map(word => <span className="word">{word}</span>)
.value()
}
</div>
)
}
}
Разбиваем слова на массив (пример 'Mathieu'.split('th') => ['Ma', 'eu'])
.map(word => word.split(target))
Затем собираем их обратно, при этом слева от каждого "кусочка" слова вставляем наш разделитель (то, что нужно выделить цветом), попутно оборачивая его в span:
.map(parts => _.reduce(
parts,
(res, part) => res.length > 0
? [ ...res, <span className="highlight">{target}</span>, part ]
: [ part ]
,
[]
))
Ну и затем оборачиваем получившийся массив в span, который будет являться контейнером для слова (результата поиска):
.map(word => <span className="word">{word}</span>)