리액트 슬랙 클론코딩 #5

Hyeonu_J·2022년 1월 23일
0
post-custom-banner

배운 것 :

Props 로 받은 값들은 deps 인자에 넣어주는 걸 잊지 말자
(useEffect, useCallback 같은 hook의 두번째 인자를 deps라고 부른다)

ChatBox/index.tsx

const ChatBox:VFC<Props> =({chat,onSubmitForm,onChangeChat,placeholder}) =>{
    // state 를 관리하는 게 아니라 태그에 직접 접근하고 싶을 때 ref 를 쓴다
    const textareaRef=useRef<HTMLTextAreaElement>(null)
    useEffect(()=>{
        if(textareaRef.current){
            autosize(textareaRef.current);
        }
    },[])
    const onKeydownChat = useCallback((e)=>{
        if(e.key==='Enter'){
            if(!e.shiftKey){
                e.preventDefault();
                onSubmitForm(e);
            }
        }
    },[onSubmitForm])
    // 여기선 deps가 onSubmitForm

WebSocket // 웹소켓이란?
실시간으로 서버와 데이터를 주고 받을 때 사용한다.
기존에 프론트 → 서버 , 서버 → 프론트 단방향 방식(논폴링)이였다면
웹소켓을 이용하여 양방향 방식으로 사용할 수 있다.

아래와 같이 사용한다.

import io from 'socket.io-client';
import React, {useCallback} from 'react';
import axios from 'axios';

const backUrl = 'http://localhost:3095';

const sockets:{[key: string]: SocketIOClient.Socket} = {}; // [key:string] 은 workspace 인데 어떤 데이터가 들어오든 문자열이면 된다 라는뜻
const useSocket = (workspace?:string) => {
    const disconnect = useCallback(() => {
        if (workspace) {
            sockets[workspace].disconnect();
            delete sockets[workspace]; // 연결 끊을 때 
        }
    },[workspace]);

    if(!workspace){
        return [undefined,disconnect];
    }
    sockets[workspace] = io.connect(`${backUrl}/ws-${workspace}`);
    sockets[workspace].emit('hello','world'); // ← 데이터 보내기
    // 서버로 hello 라는 이벤트명으로 world 라는 데이터를 보낸다
    sockets[workspace].on('message',(data)=>{ // ← 데이터 전송하기
        console.log(data);
    })
    // 서버측에서 프론트에서 데이터가 오면 message 라는 이벤트에 콜백함수 적용

    return [sockets[workspace], disconnect]
}

export default useSocket;

스크롤바를 구현하려면 react-custom-scrollbars 를 설치해준다.
명령 프롬프트에 npm install react-custom-scrollbars --save 를 실행해준다.
타입스크립트는 npm i --save-dev @types/react-custom-scrollbars 를 실행해준다.

scrollbars 는 아래와 같이 사용한다.

import Chat from '@components/Chat';
import { IDM } from '@typings/db';
import React, { useCallback, useRef, VFC } from 'react';
import Scrollbars from 'react-custom-scrollbars';
import { ChatZone, Section } from './styles';

interface Props{
    chatData?:IDM[];
    // undefined 가 '?' 를 붙여줘서 걸러진다
}

const ChatList:VFC<Props>=({chatData})=>{
    const scrollbarRef = useRef(null);
    const onScroll = useCallback(()=>{

    },[])

    return (
        <ChatZone>
            <Scrollbars autoHide ref={scrollbarRef} onScrollFrame={onScroll}>
            {chatData?.map((chat)=>(
                <Chat key={chat.id} data={chat}/>
            ))}
            </Scrollbars>
        </ChatZone>
    )
}

export default ChatList;

채팅창에 '@hw0201203' 이런 식으로 태그 언급? 하는 라이브러리

명령프롬프트에 npm i react-mentions 를 실행해 주자.
타입스크립트로 할 경우 npm i --save-dev @types/react-mentions 도 실행한다
아래처럼 사용한다

ChatBox/index.tsx

import {Mention} from 'react-mentions'

...(생략)...

    return(
        <ChatArea>
            <Form onSubmit={onSubmitForm}>
                <MentionsTextarea id="editor-chat" value={chat} onChange={onChangeChat} onKeyDown={onKeydownChat} placeholder={placeholder} ref={textareaRef}>
                    <Mention
                        appendSpaceOnAdd
                        trigger="@"
                        data={memberData?.map((v)=>({id:v.id,display:v.nickname})) || []}
                        renderSuggestion={renderSuggestion}
                    />
                </MentionsTextarea>
...(생략)...

styled components 에 관한 내용

함수를 호출하는 방법에는 여러가지가 있다.
function a() 가 있으면
a()
a.call();
a.apply();
a.bind();
등등 이런 방식으로 호출할 수 있는데

a``;

로 호출하는 방식도 있다!
이 방식을 태그드 탬플릿 리터럴이라고 부른다.
사실 styled components를 써서 만드는 css는 함수라고 볼 수 있다!
또한 탬플릿 안에다가 아래처럼 변수에 함수를 넣을 수도 있다!


export const EachMention = styled.button<{ focus: boolean }>`
  padding: 4px 20px;
  background: transparent;
  border: none;
  display: flex;
  align-items: center;
  color: rgb(28, 29, 28);
  width: 100%;
  & img {
    // & : nested selector
    margin-right: 5px;
  }

  ${({ focus }) =>
    focus &&
    `
    background: #1264a3;
    color: white;
  `};
`;

위의 gif의 ChatBox에 적용된 소스코드이다.
ChatBox/index.tsx

...(생략)...
    return(
        <ChatArea>
            <Form onSubmit={onSubmitForm}>
                <MentionsTextarea
                    id="editor-chat"
                    value={chat}
                    onChange={onChangeChat}
                    onKeyDown={onKeydownChat}
                    placeholder={placeholder}
                    inputRef={textareaRef}
                    allowSuggestionsAboveCursor
                >
                    <Mention
                        appendSpaceOnAdd
                        trigger="@"
                        data={memberData?.map((v)=>({id:v.id,display:v.nickname})) || []}
                        renderSuggestion={renderSuggestion}
                    />
                </MentionsTextarea>
...(생략)...
profile
흔한 컴공러 / 3학년
post-custom-banner

0개의 댓글