[React/TypeScript] Hooks에서 특정 요소가 보이는 위치로 스크롤

15473 단어 ReactTypeScript후크

환경


  • React v16.9
  • TypeScript v3.5.3

  • 하고 싶었던 일



    다음과 같은 메시지 화면으로 천이했을 때, 최신의 메시지의 위치까지 스크롤한 상태로 표시하고 싶었다.



    사전 준비


  • 상위 구성 요소 ChatList에는 하위 구성 요소 ChatMessage의 배열이 있습니다.
  • ※ 간략화를 위해 클래스명 등을 생략하고 있다.


  • ChatList.tsx
    import React from 'react';
    
    import { ChatRoom } from '../../interfaces/chats';
    import ChatMessage from './ChatMessage';
    
    interface Props {
      room: ChatRoom;
    }
    
    const ChatList: React.FC<Props> = ({ room }) => {
      return (
        <div>
          <div>
            {room.chats.map(chat => (
              <ChatMessage key={chat.id} chat={chat} />
            ))}
          </div>
        </div>
      );
    };
    
    export default ChatList;
    

    ChatMessage.tsx
    import React from 'react';
    
    import { Chat } from '../../interfaces/chats';
    
    interface Props {
      chat: Chat;
    }
    
    const ChatMessage: React.FC<Props> = ({ chat }) => {
      return (
        <div>
          {!chat.fromMe && (
            <div>
              <img src={chat.photo} alt="User" />
            </div>
          )}
          <div>{chat.body}</div>
        </div>
      );
    };
    
    export default ChatMessage;
    

    하위 구성 요소에서 상위 구성 요소로 ref 전달


  • 자식 구성 요소의 Props에 setRef 추가
  • useRef를 사용하여 요소에 대한 참조 얻기
  • 참고: 후크 API 참조 - useRef

  • useEffect를 사용하여 ref가 업데이트 된 시점에서 setRef를 통해 상위 구성 요소에 ref 전달

  • ChatMessage.tsx
    import React, { useEffect, useRef } from 'react';
    
    import { Chat } from '../../interfaces/chats';
    
    interface Props {
      chat: Chat;
      setRef: (chat: Chat, ref: React.RefObject<HTMLDivElement>) => void;
    }
    
    const ChatMessage: React.FC<Props> = ({ chat, setRef }) => {
      const ref = useRef<HTMLDivElement>(null);
    
      useEffect(() => {
        setRef(chat, ref);
      }, [setRef, chat, ref]);
    
      return (
        <div ref={ref}>
          {!chat.fromMe && (
            <div>
              <img src={chat.photo} alt="User" />
            </div>
          )}
          <div>{chat.body}</div>
        </div>
      );
    };
    
    export default ChatMessage;
    

    상위 구성 요소에서 마지막 요소의 위치로 스크롤


  • 하위 구성 요소에서 ref를 수신하고 스크롤하는 함수 setLastMessageElement 정의
  • 마지막 요소이면 scrollIntoView를 사용하여 요소가 보이는 위치로 스크롤합니다
  • .

  • setLastMessageElement를 하위 구성 요소에 props로 전달

  • ChatList.tsx
    import React from 'react';
    
    import { ChatRoom } from '../../interfaces/chats';
    import ChatMessage from './ChatMessage';
    
    interface Props {
      room: ChatRoom;
    }
    
    const ChatList: React.FC<Props> = ({ room }) => {
      const setLastMessageElement = (chat: Chat, ref: React.RefObject<HTMLDivElement>) => {
        const lastChat = room.chats[room.chats.length - 1];
        if (chat.id === lastChat.id) {
          ref && ref.current && ref.current.scrollIntoView();
        }
      };
    
      return (
        <div>
          <div>
            {room.chats.map(chat => (
              <ChatMessage key={chat.id} chat={chat} setRef={setLastMessageElement} />
            ))}
          </div>
        </div>
      );
    };
    
    export default ChatList;
    

    요약


  • 나중에 깨달았지만 사용자가 새 메시지를 보낼 때 chats가 업데이트되기 때문에 useEffect가 실행되어 자동으로 최신 메시지 위치로 스크롤하는 것을 알았습니다. 이것은 편리합니다.
  • 좋은 웹페이지 즐겨찾기