#html #reactjs #tags
#HTML #reactjs #Теги
Вопрос:
Я пытаюсь выяснить, упоминался ли пользователь в сообщении. Если это так, я хочу связать имя пользователя с профилем.
Что я пробовал:
if (mentions.length === 1) {
const splitSearch = '@' mentions[0].user.name;
const replaceWith =
'<a href=profile/'
mentions[0].user._id
'>@'
mentions[0].user.name
'</a>';
newText = text.split(splitSearch).join(replaceWith);
}
...
return (
...
{mentions.length > 0 amp;amp; (
<p id='text-container'>{newText}</p>
)}
Но я просто возвращаю теги в виде обычного текста:
hi <a href=profile/5f1bd6c7d90cb03e845adbbf>@user1</a>.
hello <a href=profile/5f30380288a63e001755401e>@user2</a>.
Нужно ли мне писать replaceWith
const другим способом? Я пытался Link
вместо a
, но не смог заставить это работать.
Заранее спасибо!
Ответ №1:
React может отображать только компоненты JSX.
Вместо построения HTML-строки создайте массив дочерних элементов. Когда будет найдено упоминание, поместите <a>
(элемент JSX, а не строку) в массив между его соседними дочерними элементами:
const children = text.split(splitSearch);
// Insert an `<a>` between each element:
for (let i = children.length - 1; i > 0; i--) {
const a = <a href={`profile/${mentions[0].user._id}`}>@{mentions[0].user.name}</a>;
children.splice(i, 0, a);
}
// Then render:
{mentions.length > 0 amp;amp; (
<p id='text-container'>{children}</p>
)}
Комментарии:
1. Спасибо за ваш ответ. У меня есть несколько вопросов. Почему вы используете «дочерние элементы. длина — 2»? Если бы кто-то набрал «привет @user1», это было бы просто 0, не так ли? Я пробовал как с, так и без -2. Оба раза я получаю обратно пустой массив после объединения.
2. Я все еще не могу заставить это работать. Когда я регистрирую «дочерние элементы» после объединения, у меня есть массив. Итак, это работает. Но {дочерние элементы} пусты. Поскольку объединение происходит внутри оператора if, мне нужно сказать что-то вроде «пусть children = []» перед этим, верно?
3. После того, как вы сгенерировали дочерний массив, вам нужно каким-то образом перенести его в раздел визуализации — будь то путем переназначения
children
или чего-то еще4. это работает. большое спасибо. вы знаете, как я могу отобразить упоминания? итак, упоминается более одного пользователя, каждый пользователь получает a-tag?
5. Вы могли бы использовать
.match
вместо.split
— сопоставлять все, что является упоминанием, или сопоставлять все, что не является упоминанием, чтобы разделить их, а затем использовать.map
в массиве, чтобы превратить все упоминания в<a>
s.
Ответ №2:
это неправильно.
Идея react не в том, чтобы «генерировать собственный HTML, как в вашем примере».
Вы должны использовать map внутри return (и генерировать Link
для каждого элемента в массиве) следующим образом:
return (
{
mentions.length > 0 amp;amp; (
<p id='text-container'>
{
mentions.map((m) => (
<Link key={m.user._id} to=`${m.user._id}`>
{m.user.name}
</Link>
))
}
</p>
)
}
)
Комментарии:
1. Проблема с этим: упоминание находится внутри текста. Например, «Привет @user1, что я хотел тебе сказать …». Когда я просто сопоставлю упоминания, я не смогу просто связать имя пользователя, не так ли?