I'm creating a chat application that can filter messages by hashtags
The code in my main App is like as follows:
const App = ({ }) => {
const clickTag = (msgId) => {
// scroll to ref Id
// something like ref[msgId].current.scrollIntoView();
}
{ messages.map((chat, index) => {
return (
<>
<div className="box" key={chat.id}>
<p className="ctext" id={chat.id} dangerouslySetInnerHTML={{ __html: chat.body }}></p>
</div>
<StyledSearchBar>
<SearchBar clickTag={clickTag} />
</StyledSearchBar>
</>
}
And my outside component is the <SearchBarComponent/>
const SearchBar = ({clickTag}) => {
useEffect(() => {
if (keywordSearch) {
dispatch(searchTagMessages(keywordSearch));
}
}, [keywordSearch]);
return(
<div className="header">
<div className="search-wrapper">
<SearchInput
name="seaching"
className="search-input-wrapper"
onChange={(e) => setKeywordSearch(e.target.value)}
value={keywordSearch}
/>
</div>
</div>
<div className="sidebar-content">
<div className="chatlist-container">
<ul className="chatlist">
{ msgTags.map((msg, index) => {
return (
<li className="chatlist p" key={msg.id} onClick={() => clickTag(msg.id)}>
<p className="dialog-subtitle">
<span className="user-message" id={msg.id} dangerouslySetInnerHTML={{ __html: msg.body }}></span>
</p>
</li>
)}
</ul>
)}
</div>
</div>
)
}
So when a user clicks in a specific message in SearchBar
component, the messageId
callsback in the clickTag()
function passed as props from App
component.
Then in the App
component clickTag()
function should scroll to the message ref id received msgId
.
But I didn't figure out how to create this ref's dynamically once the messageTags is received from an API.
CodePudding user response:
You can implement this feature without using useRef
.
1. Please add id
in your chatlist element. It will be used to identify the element to be scrolled.
<li id={`chatlist-${msg.id}`} className="chatlist p" key={msg.id} onClick={() => clickTag(msg.id)}>
2. Implement the scrolling logic in your main component.
const scrollToElement = (ele, offset) => {
if (!ele) return;
const rect = ele.getBoundingClientRect();
window.scrollTo({
top: rect.top window.scrollY (offset || 0),
left: 0,
behavior: 'smooth',
});
};
const clickTag = (msgId) => {
const ele = document.getElementById(`#chatlist-${msgId}`);
scrollToElement(ele);
}
You can pass top offset in 2nd parameter in scrollToElement
function.
CodePudding user response:
You could use getElementById
. First write clickTag
like this:
const clickTag = (msgId) => {
// scroll to ref Id
document.getElementById(msgId).scrollIntoView();
}
Then add the id
to each chat in the list :
<li id = {msg.id} key={msg.id} className="chatlist p" onClick={() => clickTag(msg.id)}>
<p className="dialog-subtitle">
<span className="user-message" id={msg.id} dangerouslySetInnerHTML={{ __html: msg.body }}></span>
</p>
</li>