import React from "react" ; import ChatBoard from "./ChatBoard/ChatBoard" ; import "./Container.scss" ; description interface interface IMessage { /** 메시지 인덱스 */ index : number ; /** 메시지 작성자 */ author : string ; /** 메시지 내용 */ content : string ; /** 메시지 시간 */ time : string ; /** 수정 */ isEdit : boolean ; /** 메시지 삭제*/ isDelete : boolean ; } description class implements IMessage export class Message implements IMessage { static number : number = 0 ; isDelete : boolean ; isEdit : boolean ; time : string ; index : number ; constructor ( public author = "anonymous" , public content = "" ) { this . isDelete = false ; this . isEdit = false ; this . time = `${ new Date ( ) . getHours ( ) >= 12 ? "오후" : "오전" } ${ new Date ( ) . getHours ( ) >= 12 ? new Date ( ) . getHours ( ) - 12 : new Date ( ) . getHours ( ) }:${ new Date ( ) . getMinutes ( ) >= 10 ? new Date ( ) . getMinutes ( ) : "0" + new Date ( ) . getMinutes ( ) }` ; this . index = ++ Message . number ; } } const Container = ( ) => { const [ messages , setMessages ] = React . useState ( [ ] ) ; const [ nickName , setNickName ] = React . useState ( "" ) ; const [ message , setMessage ] = React . useState ( "" ) ; const _chatBoard = React . createRef ( ) ; const _message = React . createRef ( ) ; const _nickname = React . createRef ( ) ; React . useEffect ( ( ) => { _nickname . current ?. focus ( ) ; } , [ ] ) ; description React . useEffect ( ( ) => { _message . current ?. focus ( ) ; let chat = _chatBoard . current ; if ( ! ! chat ) { chat . scrollTop = chat . scrollHeight ; } /**
         *
         *  메시지 배열에 정상적으로 들어갔다면 setMessage를 빈배열로 넣어주어 전송보냄과 동시에 message를 초기화해준다.
         * 이전에 배운 component타입에서 보았듯이 Function Component는 디테일한 제어가 힘들어
         * 클래스 컴포넌트로 한뒤에 디테일하게 배열의 길이를 기준으로 두고 초기화 시켜줄 수도 있지만, ref가 테마인지라
         * 만약 전송시에만 초기화를 시켜주고싶다면 custom hook을 사용하거나, 클래스 컴포넌트를 사용하길 바란다.
         */ setMessage ( "" ) ; } , [ messages ] ) ; description const onSave = ( e ) => { e . preventDefault ( ) ; setMessages ( [ ... messages , new Message ( nickName , message ) ] ) ; } ; description const onRemove = ( e , itemIndex ) => { e . stopPropagation ( ) ; setMessages ( messages . map ( ( item ) => ( item . index !== itemIndex ? item : { ... item , isDelete : true , isEdit : false } ) ) ) ; } ; description const onEdit = ( e , itemIndex ) => { e . stopPropagation ( ) ; setMessages ( messages . map ( ( item ) => ( item . index !== itemIndex ? item : { ... item , isEdit : true } ) ) ) ; } ; const onEditComplete = ( e , itemIndex , value ? ) => { e . stopPropagation ( ) ; setMessages ( messages . map ( ( item ) => ( item . index !== itemIndex ? item : { ... item , content : value , isEdit : false } ) ) ) ; } ; return ( < div className = "Container" > < h1 > Ref 설명을 위한 CRUD 게시판 ( Without DB ) < /h1> < h3 > Made By Sangheon . Kim < /h3> { } { ! nickName && ( < form > < label htmlFor = "message" > 닉네임 < /label> < input type = "text" name = "nickname" id = "nickname" placeholder = "20글자 미만 닉네임을 입력해주세요" ref = { _nickname } / > < button type = "submit" onClick = { ( ) => { if ( ! ! _nickname . current && _nickname . current . value . length < 20 ) { setNickName ( ! ! _nickname . current ? _nickname . current . value : "" ) ; } else { alert ( "20자 미만으로 설정해주세요" ) ; if ( ! ! _nickname . current ) { _nickname . current . value = "" ; } } } } > 접속 < /button> < /form>)} { } { ! ! nickName && ( < React . Fragment > < h1 style = { { display : "inline-block" } } > { nickName } 님 안녕하세요 . < /h1> < button onClick = { ( e ) => setNickName ( "" ) } style = { { marginLeft : 16 } } > 로그아웃 < /button> < form > < label htmlFor = "message" > 메시지 < /label> < input type = "text" ref = { _message } name = "message" id = "message" placeholder = "150자 미만 메시지를 입력해주세요" onChange = { ( e ) => e . target . value . length < 150 && setMessage ( e . target . value ) } value = { message } / > < button onClick = { ( e ) => onSave ( e ) } > 입력 < /button> < /form> < /React.Fragment>)} < ChatBoard messages = { messages } nickname = { nickName } onRemove = { onRemove } refDom = { _chatBoard } onEdit = { onEdit } onEditComplete = { onEditComplete } / > < /div>); } ; export default React . memo ( Container ) ;