Home > Net >  How to ref an map Id from outside component
How to ref an map Id from outside component

Time:04-09

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>
  • Related