인프런 커뮤니티 질문&답변

jjh099님의 프로필 이미지
jjh099

작성한 질문수

Slack 클론 코딩[실시간 채팅 with React]

커스텀 스크롤바와 dayjs

DM이 두개씩 보내져요..

작성

·

583

0

안녕하세요.

우선 저는 맥북을 사용하고 있습니다.

import { VFC, useCallback, useEffect, useRef } from 'react';
import { Form, MentionsTextarea, SendButton, Toolbox } from './styles';
import React from 'react';
import autosize from 'autosize';

interface Props {
  chat: string;
  onSubmitForm: (e: any) => void;
  onChangeChat: (e: any) => void;
  placeholder?: string;
}

const ChatBox: VFC<Props> = ({ chat, onSubmitForm, onChangeChat, placeholder }) => {
  // const onSubmitForm = useCallback(() => {}, []);
  const textareaRef = useRef(null);
  useEffect(() => {
    if (textareaRef.current) {
      autosize(textareaRef.current);
    }
  }, []);
  const onKeydownChat = useCallback(
    (e) => {
      if (e.key === 'Enter') {
        if (!e.shiftKey) {
          e.preventDefault();
          onSubmitForm(e);
        }
      }
    },
    [onSubmitForm],
  );
  return (
    <Form onSubmit={onSubmitForm}>
      <MentionsTextarea
        id="editor-chat"
        value={chat}
        onChange={onChangeChat}
        onKeyDown={onKeydownChat}
        placeholder={placeholder}
        ref={textareaRef}
      />
      <Toolbox>
        <SendButton
          className={
            'c-button-unstyled c-icon_button c-icon_button--light c-icon_button--size_medium c-texty_input__button c-texty_input__button--send' +
            (chat?.trim() ? '' : ' c-texty_input__button--disabled')
          }
          data-qa="texty_send_button"
          aria-label="Send message"
          data-sk="tooltip_parent"
          type="submit"
          disabled={!chat?.trim()}
        >
          <i className="c-icon c-icon--paperplane-filled" aria-hidden="true"></i>
        </SendButton>
      </Toolbox>
    </Form>
  );
};

export default ChatBox;

이건 제가 작성한 ChatBox입니다.

import React, { useCallback } from 'react';
import { Container, Header } from './styles';
import useSWR, { useSWRInfinite } from 'swr';
import fetcher from '@utils/fetcher';
import { useParams } from 'react-router';
import gravatar from 'gravatar';
import ChatBox from '@components/ChatBox';
import ChatList from '@components/ChatList';
import useInput from '@hooks/useInput';
import axios from 'axios';
import { IDM } from '@typings/db';
const DirectMessage = () => {
  const { workspace, id } = useParams<{ workspace: string; id: string }>();
  const { data: userData } = useSWR(`/api/workspaces/${workspace}/users/${id}`, fetcher);
  const { data: myData } = useSWR('/api/users', fetcher);
  const [chat, onChangeChat, setChat] = useInput('');
  const {
    data: chatData,
    mutate: mutateChat,
    revalidate,
  } = useSWR<IDM[]>(`/api/workspaces/${workspace}/dms/${id}/chats?perPage=20&page=1`, fetcher);

  const onSubmitForm = useCallback(
    (e) => {
      e.preventDefault();
      if (chat?.trim()) {
        axios
          .post(`/api/workspaces/${workspace}/dms/${id}/chats`, {
            content: chat,
          })
          .then(() => {
            revalidate();
            setChat('');
            console.log('submit');
          })
          .catch((error) => {
            console.log(error);
          });
      }
    },
    [chat],
  );

  if (!userData || !myData) {
    return null;
  }

  return (
    <Container>
      <Header>
        <img src={gravatar.url(userData.email, { s: '24px', d: 'retro' })} alt={userData.nickname} />
        <span>{userData.nickname}</span>
      </Header>
      <ChatList chatData={chatData} />
      <ChatBox chat={chat} onChangeChat={onChangeChat} onSubmitForm={onSubmitForm} />
    </Container>
  );
};

export default DirectMessage;

이건 DirectMessage 입니다.

e.preventDefault()로 기본 이벤트를 막아줬는데도 DM을 엔터로 전송하면 (한글로만 전송하면 2개씩 보내져요...!)어떨때는 2개가 보내지고 어떨때는 1개가 보내져요... 네트워크나 콘솔에도 2개씩 뜨고요.. 전송버튼을 눌렀을때는 1개만 보내집니다.

 

 

답변 2

1

저도 같은 문제를 겪었습니다!


이전에는 안 그러다가 저도 같은 부분에서 문제가 발생해서 좀 당황스럽더라구요 ㅎㅎ;

 

구글링한 결과, 한글이 조합 문자라서 입력 시에, 이상하게 이벤트가 2번 발생하는 문제가 있다고 하더라구요.(아마 맥 환경에서만 그런 것 같습니다.)


중간에 e.nativeEvent.isComposing === false 추가해주시면 해결되는 것 같습니다.

const onKeyDownChat = useCallback(
    (e) => {
      if (e.key === 'Enter') {
        if (e.nativeEvent.isComposing === false && !e.shiftKey) {
          e.preventDefault();
          onSubmitForm(e);
        }
      }
    },
    [onSubmitForm],
  );

 https://velog.io/@corinthionia/JS-keydown%EC%97%90%EC%84%9C-%ED%95%9C%EA%B8%80-%EC%9E%85%EB%A0%A5-%EC%8B%9C-%EB%A7%88%EC%A7%80%EB%A7%89-%EC%9D%8C%EC%A0%88%EC%9D%B4-%EC%A4%91%EB%B3%B5-%EC%9E%85%EB%A0%A5%EB%90%98%EB%8A%94-%EA%B2%BD%EC%9A%B0-%ED%95%A8%EC%88%98%EA%B0%80-%EB%91%90-%EB%B2%88-%EC%8B%A4%ED%96%89%EB%90%98%EB%8A%94-%EA%B2%BD%EC%9A%B0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

감사합니다!!

jjh099님의 프로필 이미지
jjh099
질문자

커뮤니티 내에서 좀 더 찾아볼 걸 그랬네요.
감사합니다!

jjh099님의 프로필 이미지
jjh099

작성한 질문수

질문하기