React(Next.js)가 제작한 채팅 바람 퀘스트 답장 기능

52891 단어 Next.jsReacttech

할 수 있는 일



전제 조건


Next.js 학습 중
채팅 화면 설치에 관한 비망록으로 기재
상대는 미션을 기억하는 로봇.
앞의 글만 있지만 앞에 생성된 배열 데이터 부분을 API를 두드리는 행위로 백엔드와 연결하면 데이터를 저장할 수 있다고 생각합니다.
만약 이후에post 인증 기능과 사용자 간의 시계를 사용할 수 있다면, 사용자 간에 채팅을 할 수 있고, 기뻐서 껑충껑충 뛸 수 있을 것이다

설치 내용


  • 이 단어를 기억하고 미션을 입력하면 기억해요.

  • 알려주시면 보내주시면 미션이 돌아갑니다.

  • [amp]lt;Enter[amp]gt; 키를 눌러 양식을 전송하는 행위

  • 채팅 대상과 자신의 데이터를 한데 배열하여 표지로 누구의 발언을 판단하고 CSS의 기능을 동태적으로 변경한다

  • 그룹에서 배열된 구현 (채팅에 등록된 작업 목록 보이기)

  • 자동 스크롤 기능은 항상 최신 문장에 초점을 맞춘다

  • 자동 응답 기능

  • 자동 회신 기능 회신 대기 시 연속 투하 불가 기능

  • 발송 후 창을 비우는 기능

  • 배열에 데이터를 추가한 다음에 화면에 즉시 반영합니다. 이것은 React에서push가 할 수 없는 것 같습니다. 매번 추가된 데이터는 배열 자체를 업데이트합니다
  • 언어, 라이브러리, 프레임워크 및 플러그인 사용

  • Next.js
  • typeScript
  • styled-components
  • react-custom-scrollbars-2
  • iconify
  • 만약 무슨 의견이나 개선된 점이 있다면, 저에게 말씀해 주신다면, 저는 매우 감사하겠습니다.나 자신도 개선에 힘쓸 것이다.

    코드


    import styled from "styled-components";
    import React, { useState, useEffect, useRef, useLayoutEffect } from "react";
    import { Icon } from '@iconify/react';
    import { Scrollbars } from "react-custom-scrollbars-2";
    
    const style = {
      width: "100%",
      height: "500px",
    };
    
    
    const ChatPage = () => {
    
      const footRef = useRef(null)
      const [content, setContent] = useState([])
      const [rememberContent, setRememberContent] = useState([])
      const [phrase, setPhrase] = useState("")
      const [changeColor, setChangeColor] = useState("#e0e0e0")
      const [stop, setStop] = useState(false)
      const [remember, setRemember] = useState(false)
    
    
      const handleKeyDown = (e) => {
    
        if (stop) { return }
    
        if (e.keyCode === 13) {
          if (!phrase) { return }
    
          setContent([
            ...content, {
              user: 1,
              word: phrase,
              side: "flex-end"
            }])
    
          setPhrase("")
        }
      }
    
      const handleSubmit = () => {
        if (stop) { return }
        setContent([
          ...content, {
            user: 1,
    	// user:1が自分、user:2が相手(ユーザー間だったらuser_idとか入れたい)
            word: phrase,
            side: "flex-end"
          }])
    
        setPhrase("")
      }
    
      const replay = () => {
        const flag = content.slice(-1)[0]
    
        if (!flag) { return }
    
        if (flag.user == 1) {
          if (flag.word.match(/remember|覚えて/)) {
            setStop(true)
    
            setTimeout(function () {
              setContent([
                ...content, {
                  user: 2,
                  word: "何を覚えますか?",
                  side: "flex-start"
                }]), setRemember(true), setStop(false)
            }, 1000)
          }
    
          if (remember == true) {
            setRememberContent([...rememberContent, {
              word: flag.word,
              complete: false,
              side: "flex-start"
            }])
            setRemember(false)
    
            setTimeout(function () {
              setContent([
                ...content, {
                  user: 2,
                  word: "覚えました",
                  side: "flex-start"
                }])
            }, 1000)
          }
    
          if (flag.word.match(/教えて|notify/)) {
            setStop(true)
    
            setTimeout(function () {
              setContent([
                ...content, {
                  user: 2,
                  word: "こちらです",
                  side: "flex-start",
                  rememberContent: rememberContent
                }]), setStop(false)
            }, 1000)
          }
    
          if (flag.word.match(/こんにちは/)) {
    
            setStop(true)
    
            const num = Math.floor(Math.random() * 2)
            const kuji = ['こんにちは', 'どうかされましたか?'][num]
    
            setTimeout(function () {
              setContent([
                ...content, {
                  user: 2,
                  word: kuji,
                  side: "flex-start"
                }]), setStop(false)
            }, 1000)
          }
    
          if (flag.word.match(/画像/)) {
            setStop(true)
    
            setTimeout(function () {
              setContent([
                ...content, {
                  user: 2,
                  word: "どうぞ",
                  image: "任意の画像.png",
                  side: "flex-start"
                }]), setStop(false)
            }, 1000)
          }
        } else if (flag.user == 2) {
          if (flag.word.match(/どうかされましたか?/)) {
    
            setTimeout(function () {
              setContent([
                ...content, {
                  user: 2,
                  word: `${"覚えて と送信したあとに打ち込んだ言葉を覚えます。教えて と送信すると覚えた言葉を返します。"}`,
                  side: "flex-start"
                }])
            }, 1000)
          }
        }
      }
      
      useEffect(() => {
        replay()
      }, [content]);
    
      useLayoutEffect(() => {
        if (footRef.current) {
          footRef.current.scrollIntoView();
        }
      }, [content]);
    
      return (
        <>
          <Span>
          </Span>
          <Scrollbars style={style}>
            <Display color={changeColor}>
              <Column>
                {content.map((phraseArray, index) => (
                  <div key={phraseArray}>
                    <Phrase side={phraseArray.side}>
                      <Background>
                        {phraseArray.word}
                      </Background>
                    </Phrase>
                    {function () {
                      if (phraseArray.image) {
                        return (
                          <Phrase side={phraseArray.side}>
                            <ImageBackground>
                              <ChatImage src={phraseArray.image} />
                            </ImageBackground>
                          </Phrase>
                        )
                      }
                    }()}
                    {function () {
                      if (phraseArray.rememberContent) {
                        return (<>
                          <Phrase side={"flex-start"}>
                            <ListBackground>
                              {
                                rememberContent.map((rememberArray) => (
                                  <div key={rememberArray}>{rememberArray.word}
                                  </div>
                                ))
                              }
                            </ListBackground>
                          </Phrase>
                        </>
                        )
                      }
                    }()}
    
                    {index === content.length - 1 && <div ref={footRef}></div>}
                  </div>
                ))}
    
              </Column>
    
            </Display>
          </Scrollbars>
    
          <InputFormArea>
            <Form>
              <TextInputArea
                onKeyDown={(e) => handleKeyDown(e)}
                onChange={(event) => setPhrase(event.target.value)}
                value={phrase}
              >
    
              </TextInputArea>
              <SubmitButton
                onClick={() => handleSubmit()}
              >
                <Icon icon="fluent:send-16-regular" width="20" height="20" />
              </SubmitButton>
    
            </Form>
    
          </InputFormArea>
        </>
      );
    };
    
    export default ChatPage;
    
    
    const ChatImage = styled.img`
    max-width:90%;
    object-fit:cover;
    `
    
    const Span = styled.div`
    height:50px;
    width:100%;
    `
    
    const Background = styled.div`
    background-color:white;
    height:100%;
    min-height:45px;
    padding:10px 20px;
    border-radius:10px;
    display:flex;
    align-items: center;
    text-align:left;
    max-width:70%;
    `
    
    const ListBackground = styled.div`
    background-color:white;
    height:100%;
    min-height:45px;
    padding:10px 20px;
    border-radius:10px;
    display:flex;
    align-items: flex-start;
    text-align:left;
    max-width:70%;
    flex-flow:column;
    `
    
    const ImageBackground = styled.div`
    height:100%;
    min-height:45px;
    padding:10px 0px;
    border-radius:10px;
    display:flex;
    align-items: center;
    text-align:left;
    max-width:70%;
    `
    
    const Column = styled.span`
    width:100%;
    height:100%;
    margin:0 auto;
    display:flex;
    flex-direction: column;
    justify-content: flex-end;
    `
    
    const Phrase = styled.div<any>`
    width:90%;
    text-align:right;
    min-height:45px;
    margin :0 auto 15px;
    display:flex;
    justify-content:${(props) => props.side};
    align-items: center;
    `
    
    const Form = styled.div`
    display:flex;
    width:90%;
    height:70%;
    justify-content: center;
    justify-content: space-between;
    `
    
    const SubmitButton = styled.button`
    margin-left:15px;
    width:80px;
    border-radius:10px;
    border:none;
    color:#666666;
    padding:2px 0 0 2px;
    `
    
    const TextInputArea = styled.input`
    width: calc(100% - 80px);
    border-radius:10px;
    border:1px solid #e0e0e0;
    background-color:#fbf9ff;
      text-indent: 1em;
      &:focus {
        outline: none;
        border: 2px solid#666666;
      }
    `
    
    const Display = styled.div`
    width:70%;
    max-width:600px;
    min-height:500px;
    margin: 0 auto ;
    background-color:${(props) => props.color};
    border:solid 1px #e0e0e0;
    border-radius:10px;
    display:flex;
    justify-content: center;
    align-items: flex-end;
    padding-top:15px;
    `
    
    const InputFormArea = styled.div`
    width:70%;
    max-width:600px;
    height:50px;
    margin:10px auto 0;
    border-radius:10px;
    background-color:#e0e0e0;
    border:solid 1px #e0e0e0;
    display:flex;
    align-items: center;
    justify-content:center;
    `
    
    

    결실



    보태다


    만약 이 기능에 인증 기능을 더하면 사용자끼리 채팅을 할 수 있기 때문에 반드시 실현해야 한다.

    좋은 웹페이지 즐겨찾기