React(Next.js)가 제작한 채팅 바람 퀘스트 답장 기능
할 수 있는 일
전제 조건
Next.js 학습 중
채팅 화면 설치에 관한 비망록으로 기재
상대는 미션을 기억하는 로봇.
앞의 글만 있지만 앞에 생성된 배열 데이터 부분을 API를 두드리는 행위로 백엔드와 연결하면 데이터를 저장할 수 있다고 생각합니다.
만약 이후에post 인증 기능과 사용자 간의 시계를 사용할 수 있다면, 사용자 간에 채팅을 할 수 있고, 기뻐서 껑충껑충 뛸 수 있을 것이다
설치 내용
이 단어를 기억하고 미션을 입력하면 기억해요.
알려주시면 보내주시면 미션이 돌아갑니다.
[amp]lt;Enter[amp]gt; 키를 눌러 양식을 전송하는 행위
채팅 대상과 자신의 데이터를 한데 배열하여 표지로 누구의 발언을 판단하고 CSS의 기능을 동태적으로 변경한다
그룹에서 배열된 구현 (채팅에 등록된 작업 목록 보이기)
자동 스크롤 기능은 항상 최신 문장에 초점을 맞춘다
자동 응답 기능
자동 회신 기능 회신 대기 시 연속 투하 불가 기능
발송 후 창을 비우는 기능
배열에 데이터를 추가한 다음에 화면에 즉시 반영합니다. 이것은 React에서push가 할 수 없는 것 같습니다. 매번 추가된 데이터는 배열 자체를 업데이트합니다
언어, 라이브러리, 프레임워크 및 플러그인 사용
코드
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;
`
결실
보태다
만약 이 기능에 인증 기능을 더하면 사용자끼리 채팅을 할 수 있기 때문에 반드시 실현해야 한다.
Reference
이 문제에 관하여(React(Next.js)가 제작한 채팅 바람 퀘스트 답장 기능), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/neiri_tech/articles/fc9776bb78e705텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)