react (댓글폼)

오미희·2021년 7월 13일
0

react

목록 보기
4/15

폼만 고정적으로 만들어진 상태 추가적인 댓글은 불가능

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
    
    <div id="root">
    </div>
    <script type="text/babel">

        class ComponentForm extends React.Component{

            render(){           
                return(
                <>
                    <li className="comment-form">
                        <form>
                            <h4>댓글쓰기 <span>(3)</span></h4>
                            <span className="ps_box">
                                <input type="text" placeholder="댓글내용을 입력해주세요." className="int"/>
                            </span>
                            <input type="submit" value="등록" className="btn"/>
                        </form>
                    </li>
                </>
                )               
            }
        }

        class ComponentRow extends React.Component{
            render(){
               
                return(
                    <>
                    <li>
                        <ul className="comment-row">
                            <li className="comment-id">algml</li>
                            <li className="comment-content">안녕하세요.</li>
                            <li className="comment-content">반갑습니다.</li>
                        </ul>
                    </li>
                </>
                )                
            }
        }

        class CommentApp extends React.Component{
            render(){

                return(
                    <>                       
                            <ComponentRow/>
                            <ComponentRow/>
                            <ComponentRow/>                            
                            <ComponentForm/>
                            
                        
                    </>
                )
            }
        }
// javascript + XML = jsx

// xml => 예전에 데이터 주고받던 형식
        ReactDOM.render(
            <CommentApp/>,
            document.querySelector('#root')
        )
    </script>
</body>
</html>

댓글 삭제 추가까지 가능한 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <link rel="stylesheet" href="./example6.css">
</head>
<body>
    
<div id="root">
   
</div>
<script type="text/babel">
    /*
        JSX = javascript + xml
    */
    class CommentForm extends React.Component{
        state = {
            content:'',
        }

        handleChange = (e) => {
            this.setState({[e.target.name]:e.target.value})
        }

        handleSubmit = (e) => {
            e.preventDefault()
            this.props.onCreate(this.state.content)
            this.setState({content:''})
        }

        render(){
            return (
                <li className="comment-form">
                    <form onSubmit={this.handleSubmit}>
                        <h4>댓글쓰기 <span>({this.props.count})</span></h4>
                        <span className="ps_box">
                            <input 
                                type="text" 
                                placeholder="댓글내용을 입력해주세요." 
                                className="int" 
                                name="content"
                                value={this.state.content}
                                onChange={this.handleChange}
                            />
                        </span>
                        <input type="submit" value="등록" className="btn" />
                    </form>
                </li>
            );
        }
    }
    
    class CommentList extends React.Component{
        state = {
            content:'',
            key:Infinity,
        }

        handleClick = (key) => {
            this.setState({key:key})
        }

        handleChange = (e) => {
            this.setState({ [e.target.name]:e.target.value })
        }

        handleEnter = (e) => {
            if(e.key === 'Enter'){
                let {key,content} = {...this.state}
                this.props.onUpdate(key,content)
                this.setState({key:Infinity,content:''})
            }
        }

        inputBox = (content) => {
            return(
                <input
                    type="text" 
                    className="comment-update-input" 
                    name="content"
                    defaultValue={content}
                    onChange={this.handleChange}
                    onKeyDown={this.handleEnter}
                />
                )
        }

        renderList = () => {
            return(
                this.props.items.map((item,key)=>{
                    return(
                        <li key={key}>
                            <ul className="comment-row">
                                <li className="comment-id">{item.userid}</li>
                                <li className="comment-content">
                                    
                                    <span onClick={()=>{ this.handleClick(key) }}>
                                        {key === this.state.key ? this.inputBox(item.content) : item.content}
                                    </span>
                                    <span 
                                        className="comment-delete-btn"
                                        onClick={ ()=>{this.props.onDelete(key)} }
                                    >
                                        X
                                    </span>
                                </li>
                                <li className="comment-date">{item.date}</li>
                            </ul>
                        </li>
                    )
                })
            )
        }

        input = 0

        render(){
            return (
                <>
                    {this.renderList()}
                </>
            );
        }
    }

    class CommentLayout extends React.Component{
        render(){
            return(
                <ul className="comment">
                    {this.props.children}
                </ul>
            )
        }
    }

    class Comment extends React.Component{ // 모든 댓글기능이 다그려지는 역활
        state = {
            list:[]
        }

        getToday = () => {
            let date = new Date();
            let year = date.getFullYear();
            let month = ("0"+(1+date.getMonth())).slice(-2)
            let day = ("0" + date.getDate()).slice(-2)
            let hour = ("0"+((date.getHours())-12)).slice(-2)
            let minute = ("0"+date.getMinutes()).slice(-2)
            let second = ("0"+date.getSeconds()).slice(-2)
            return `${year}-${month}-${day} ${hour}-${minute}-${second}`;
        }

        onCreate = (data) => { // 일단 댓글쓸때 사용할 함수를 미리 선언
            let item = {userid:'algml0703',content:data,date:this.getToday()}
            let {list} = {...this.state} // 내현재 state list를 복사해서 list라는 변수에 넣겠다.
            let newList = [...list,{...item}] // 새로운변수를 선언해서 list라는 변수와, item이라는 변수를 넣어서 새로만들겠다.
            
            this.setState({list:newList})
        }

        onUpdate = (index,content) => {
            let {list} = {...this.state}
            list[index].content = content
            this.setState({list:list})
        }

        onDelete = (data) => {
            //data 변수 1 
            let {list} = {...this.state}
            let newList = list.filter((value,index)=>{
                return data !== index
            })

            this.setState({list:newList})
        }
        
        componentDidMount(){ //생명주기 
            let list = [
                {userid:'algml0703',content:'안녕하세요 반갑습니다.',date:'2021-07-01'},
                {userid:'algml0703',content:'안녕하세요 처음 뵙겠습니다.',date:'2021-07-01'},
                {userid:'algml0703',content:'안녕하세요 제 이름은',date:'2021-07-01'},
            ]
            this.setState({list:list})
        }

        render(){
            return(
                <CommentLayout>
                    <CommentForm 
                        onCreate={this.onCreate}
                        count={this.state.list.length}
                    />
                    <CommentList 
                        items={this.state.list}
                        onDelete={this.onDelete}
                        onUpdate={this.onUpdate}
                    />
                </CommentLayout>
            )
        }
    }

    class App extends React.Component{
        render(){
            return(
                <Comment />
            )
        }
    }

    ReactDOM.render(
        <App />,
        document.querySelector('#root')
    )
</script>
</body>
</html>

업데이트까지 구현된 코드

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>리액트 시간</title>
    <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <link rel="stylesheet" href="./example6.css">
</head>
<body>
    
<div id="root">
    <!--
    <ul class="comment">
        <li>
            <ul class="comment-row">
                <li class="comment-id">algml0703</li>
                <li class="comment-content">안녕하세요 반갑습니다.</li>
                <li class="comment-date">20221-06-28</li>
            </ul>
        </li>
        <li>
            <ul class="comment-row">
                <li class="comment-id">algml0703</li>
                <li class="comment-content">안녕하세요 반갑습니다.</li>
                <li class="comment-date">20221-06-28</li>
            </ul>
        </li>
        <li>
            <ul class="comment-row">
                <li class="comment-id">algml0703</li>
                <li class="comment-content">안녕하세요 반갑습니다.</li>
                <li class="comment-date">20221-06-28</li>
            </ul>
        </li>
        <li class="comment-form">
            <form>
                <h4>댓글쓰기 <span>(3)</span></h4>
                <span class="ps_box">
                    <input type="text" placeholder="댓글내용을 입력해주세요." class="int"/>
                </span>
                <input type="submit" value="등록" class="btn"/>
            </form>
        </li>
    </ul>
    -->
</div>
<script type="text/babel">
    /*
        JSX = javascript + xml
    */
    class CommentForm extends React.Component{
        state = {
            content:'',
        }

        handleChange = (e) => {
            this.setState({[e.target.name]:e.target.value})
        }

        handleSubmit = (e) => {
            e.preventDefault()

            this.props.onCreate(this.state.content)
            this.setState({content:''})
        }

        render(){
            return (
                <li className="comment-form">
                    <form onSubmit={this.handleSubmit}>
                        <h4>댓글쓰기 <span>({this.props.count})</span></h4>
                        <span className="ps_box">
                            <input 
                                type="text" 
                                placeholder="댓글내용을 입력해주세요." 
                                className="int" 
                                name="content"
                                value={this.state.content}
                                onChange={this.handleChange}
                            />
                        </span>
                        <input type="submit" value="등록" className="btn" />
                    </form>
                </li>
            );
        }
    }
    class CommentList extends React.Component{
        state = {
            content:'',
            key:Infinity,
        }

        handleClick = (key) => {
            this.setState({key:key})
        }

        handleChange = (e) => {
            this.setState({ [e.target.name]:e.target.value })
        }

        handleEnter = (e) => {
            if(e.key === 'Enter'){
                let {key,content} = {...this.state}
                this.props.onUpdate(key,content)
                this.setState({key:Infinity,content:''})
            }
        }

        inputBox = (content) => {
            return(
                <input
                    type="text" 
                    className="comment-update-input" 
                    name="content"
                    defaultValue={content}
                    onChange={this.handleChange}
                    onKeyDown={this.handleEnter}
                />
                )
        }

        renderList = () => {
            return(
                this.props.items.map((item,key)=>{
                    return(
                        <li key={key}>
                            <ul className="comment-row">
                                <li className="comment-id">{item.userid}</li>
                                <li className="comment-content">
                                    
                                    <span onClick={()=>{ this.handleClick(key) }}>
                                        {key === this.state.key ? this.inputBox(item.content) : item.content}
                                    </span>
                                    <span 
                                        className="comment-delete-btn"
                                        onClick={ ()=>{this.props.onDelete(key)} }
                                    >
                                        X
                                    </span>
                                </li>
                                <li className="comment-date">{item.date}</li>
                            </ul>
                        </li>
                    )
                })
            )
        }

        input = 0

        render(){
            return (
                <>
                    {this.renderList()}
                </>
            );
        }
    }

    class CommentLayout extends React.Component{
        render(){
            return(
                <ul className="comment">
                    {this.props.children}
                </ul>
            )
        }
    }

    class Comment extends React.Component{ // 모든 댓글기능이 다그려지는 역활
        state = {
            list:[]
        }
        
        onCreate = (data) => { // 일단 댓글쓸때 사용할 함수를 미리 선언
            let item = {userid:'algml0703',content:data,date:'2021-07-01'}
            let {list} = {...this.state} // 내현재 state list를 복사해서 list라는 변수에 넣겠다.
            let newList = [...list,{...item}] // 새로운변수를 선언해서 list라는 변수와, item이라는 변수를 넣어서 새로만들겠다.
            
            this.setState({list:newList})
        }

        onUpdate = (index,content) => {
            let {list} = {...this.state}
            list[index].content = content
            this.setState({list:list})
        }

        onDelete = (data) => {
            //data 변수 1 
            let {list} = {...this.state}
            let newList = list.filter((value,index)=>{
                return data !== index
            })

            this.setState({list:newList})
        }
        
        componentDidMount(){ //생명주기 
            let list = [
                {userid:'algml0703',content:'안녕하세요 댓글이에요1',date:'2021-07-01'},
                {userid:'algml0703',content:'안녕하세요 댓글이에요2',date:'2021-07-01'},
                {userid:'algml0703',content:'안녕하세요 댓글이에요3',date:'2021-07-01'},
            ]
            this.setState({list:list})
        }

        render(){
            return(
                <CommentLayout>
                    <CommentForm 
                        onCreate={this.onCreate}
                        count={this.state.list.length}
                    />
                    <CommentList 
                        items={this.state.list}
                        onDelete={this.onDelete}
                        onUpdate={this.onUpdate}
                    />
                </CommentLayout>
            )
        }
    }

    class App extends React.Component{
        render(){
            return(
                <Comment />
            )
        }
    }

    ReactDOM.render(
        <App />,
        document.querySelector('#root')
    )
</script>
</body>
</html> 

css

*{margin:0; padding:0;}
body{
    font-family: 'Noto Sans KR', sans-serif;
    font-weight:300;
}
ul,li{
    list-style:none;
}

.comment{
    display:flex;
    flex-direction: column;
    flex-wrap: nowrap;
    padding:30px;
    width:600px;
    margin:0 auto;
    
}

.comment > li{ margin-top:20px; }
.comment > li:nth-child(1){ margin:0px;}

.comment-row{
    display:flex;
    justify-content: space-between;
    flex-direction: row;
}

.comment-row{
    margin-top:20px;
    width:100%;
}

.comment-row > li:nth-child(2){
    flex-shrink: 0;
    flex-grow: 1;
    padding-left:25px;
    z-index:1;
    width:100%;
}

.comment-row > li:nth-child(2){
    width:85px;
}

.comment-form > form{
    display:flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
}

.comment-form > form > h4{
    width:100%;
    margin:14px 0 14px 0;
}

.comment-content{
    word-break:break-all;
    padding-right:25px;
}

.ps_box{
    display: block;
    position: relative;
    width: 80%;
    height: 51px;
    border: solid 1px #dadada;
    padding: 10px 14px 10px 14px;
    background: #fff;
    box-sizing: border-box;
}

.ps_box > input{
    outline:none;
}

.int{
    display: block;
    position: relative;
    width: 100%;
    height: 29px;
    padding-right: 25px;
    line-height: 29px;
    border: none;
    background: #fff;
    font-size: 15px;
    box-sizing: border-box;
    z-index: 10;
}

.btn{
    width:18%;
    padding: 18px 0 16px;
    text-align: center;
    box-sizing: border-box;
    text-decoration: none;
    border:none;
    background:#333;
    color:#fff;
    font-size:14px;
}

.comment-delete-btn{
    display:inline-block;
    margin-left:7px;
    cursor: pointer;
}

.comment-update-input{
    border:none;
    border-bottom: 1px solid #333;
    font-size:16px;
    color:#666;
    outline: none;
}
profile
안녕하세요

0개의 댓글