inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

커스텀 스크롤바와 dayjs

DM이 두개씩 보내져요..

708

jjh099

작성한 질문수 6

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개만 보내집니다.

 

 

react 웹팩 typescript socket.io babel 클론코딩

답변 2

1

Chanhyung Lee

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


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

 

구글링한 결과, 한글이 조합 문자라서 입력 시에, 이상하게 이벤트가 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

1

제로초(조현영)

감사합니다!!

1

제로초(조현영)

https://www.inflearn.com/questions/273222/%ED%95%9C%EA%B8%80%EC%9E%85%EB%A0%A5%EC%8B%9C-%EC%B1%84%ED%8C%85%EC%9D%B4-%EB%91%90%EA%B0%9C%EC%94%A9-%EA%B0%80%EB%8A%94-%EC%98%A4%EB%A5%98

이거 종종 나오는 질문인데, 어딘가에 코드 오타가 있을 확률이 높습니다.

0

jjh099

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

기본 셋팅과 관련하여

0

92

1

초기 셋팅 back과 front만 남겨두고 다 지운 후 진행 방법

0

96

2

focus 시에만 화면 업데이트 되는 이유 + 해결방법

0

150

2

useEffect 개수 관리

0

110

2

라이브러리 서치 방법

0

104

2

함수 정의 패턴

0

77

1

npm run dev 에러

0

152

3

npx webpack 후 에러

0

178

2

'void' 형식 식의 truthiness를 테스트할 수 없습니다.ts(1345)

0

144

2

사용자 가입시 에러발생 (TypeError: Cannot read properties of null (reading 'addMembers')

1

178

2

초기세팅중 packge.json 에러떠요

0

156

2

CORS - Access-Control-Allow-Origin 누락 문제

0

431

3

로그인 페이지 무한 새로고침 현상

0

598

2

Module not found: Error: Can't resolve './App' 에러

0

959

1

배포 방법

0

297

2

npm run dev 시 빌드가 매우 느려졌습니다

0

990

2

alias 경로 설정 오류

0

451

2

fetcher 함수의 data 값이 두번 찍히는 이유

0

277

1

제네릭 질문

0

218

2

ts-node 대신 tsx 사용여부

0

373

1

배포 관련 질문

0

247

1

[nginx + https] 서비스를 실행하면 niginx가 아닌 서비스 화면을 보여주게 하고 싶습니다.

0

385

2

[배포하기] webpack에 aws 퍼블릭 IPv4 주소 와 포트 주소를 작성하고 나서 빌드후 실행하면 오류가 발생합니다.

0

336

1

users 호출 시 쿠키가 담기지 않는 이슈 질문드립니다.

0

247

2