프론트엔드/React

[React/javascript] 댓글 CRUD 구현하기

청포도 에이드 2022. 4. 22. 17:45
728x90
App.jsx

 

class App extends Component{

    state = {
        value:'hello world!!!!',
        list:[]   
    }

    // 생명주기 함수 
    componentDidMount(){ // 최초실행 후(화면 랜더 후) 실행되는 함수.
        this.setState({ // 불변성...  데이터가 화면이바뀐다.
            ...this.state,
            list:[
                {userid:'web7722',content:'안녕하세요2',date:"2022-04-21", updateflag:true},
                {userid:'web7722',content:'안녕하세요3',date:"2022-04-21", updateflag:true},
                {userid:'web7722',content:'안녕하세요4',date:"2022-04-21", updateflag:true}
            ]
        })
    }

    // content : stirng
    // obj
    //댓글 Create
    addList = (obj) => {
        this.setState({
            list:[...this.state.list, obj]
        })
    }
    //obj라는 배열(새로운 댓글 입력)이 들어오면,
    //기존 state는 그대로 유지하되, list안에 obj만 추가해준다.

	//댓글 수정
    updateList = list => {
        this.setState({
            ...this.state,
            list
        })
    }
	//기존 state에서 새로 들어온 list라는 배열만 치환해준다.


    render(){
        const { list } = this.state
        return(
            <>
                <Comment> 
                    <CommentForm addList={ this.addList }
                    /> 
                    <CommentList list={ list }
                    updateList={this.updateList}
                    /> 
                </Comment> 
                
            </>
        )
    }
}


export default App;

 

Comment.jsx

 

 

import React,{Component} from 'react'

class Comment extends Component{

    

    render(){
        return(
            <ul className="comment">
              {this.props.children} 
            </ul>
        )
    }
}

export default Comment

this.props.children으로 상위 컴포넌트인 App 컴포넌트, <Comment></Comment> 안에 작성한 HTML을 끌어온다.

 

이 부분 ↓

<Comment> 
    <CommentForm addList={ this.addList }
    /> 
    <CommentList list={ list }
    updateList={this.updateList}
    /> 
</Comment>

 

CommentForm.jsx

 

class CommentForm extends Component{

    state = {
        value: ''
    }

    handleChange = e => {
        const { value } = {...e.target}
        // e.target만 쓰면 타자를 칠때마다 한글자씩만 value에 담긴다
        this.setState({
            value
        })
    }

    handleSubmit = e => {
        e.preventDefault()
        console.log(this.state.value)
        // axios 가발동.
        // 결과물을 줄때. 그때 상태를 바꾸면되여.
        // then 콜백 함수 안에서 상태를 바꾸시면 됩니다.
        const obj = {userid:'web7722',content:this.state.value,date:"2022-04-21", updateflag:true}
        
        this.props.addList(obj)
        this.setState({
            value:'',
            //반복적인 내용 제출을 막기위해 value값을 비워준다.

        })
        // Submit 버튼을눌렀을때. input박스에잇는 내용을 쉽게 가져올수있게 처리는함.
        // input.value는 쉽게 가지고올수있는 상태

        // App컴포넌트에 있는 list라는 값을 push 해줘야하는 상황이에요, 
            // App컴포넌트에서 상태를 바꿀수있는 함수를만듭시다,
            // App컴포넌트에서 상태를 바꿀수있는 함수를, CommentForm 컴포넌트에게 props로 함수를 전달해줍시다.
            // handleSubmit 함수가 호출되었을때 props 로 전달받은 함수를 실행시킬거에요, 
            // props로 전달받은 함수는 CommentForm 에서 받은 상태 value값을 인자값으로 넣어준다,
            // CommentForm 에 있는 value라는 상태값을 '' 빈 문자열로 상태를 바꾼다~
    }

    // 
    render(){
        return(
            <li className="comment-form">
                <form onSubmit={this.handleSubmit}>
                    <span className="ps_box">
                        <input 
                            type="text" 
                            className="int"
                            placeholder="댓글을 입력해 주세요."
                            onChange={this.handleChange}
                            value={this.state.value}
                        />
                    </span>
                    <input type="submit" className="btn" value="등록" />
                </form>
            </li>
        )
    }
}

export default CommentForm

 

CommentList.jsx

 

import React,{Component} from 'react'

class CommentList extends Component{


    state = {
        value:"",
        update:null
    }
    /*
        CommentList에서 상태를 만들었다면.
        뿌리는 데있어가지곤 엄청쉽다! 

        CommnetForm 같이 생각을해봐야됨.

        state = {
            list:[
                {id,documet.querySelector('.int').value ,date},
                {id,content,date}
            ]
        }
    */
   input = React.createRef()

   
    handleClick = (i) => e => {
        console.log(e.target.innerHTML)
        this.setState({
            ...this.state,
            value:e.target.innerHTML,
            update:i
        })
    }

    updateChange = e => {
        const {value} = {...e.target}

        this.setState({
            ...this.state,
            value
        })
    }

    updateKeyDown = i => e => {
        if(e.key !=='Enter') return
        const {updateList, list} = this.props
        // list
        const newList = [...list]
        newList[i].content = this.state.value
        this.setState({
            ...this.state,
            update:null
        })

        updateList(newList)
    }

    deleteClick = k=> {
        const {updateList,list} = this.props
        const newList = [...list].filter((v,i)=> i !== k)
        console.log(newList)

        updateList(newList)

        // const deleteArr = []
        // for(let i =0; i>newList.length; i++){
        //     if(i !== k){
        //         deleteArr.push(newList[i])
        //     }
        // }

        // console.log(deleteArr)

        // const deleteArr = newList.filter((v,i)=>{
        //     return i !== k
        // })

        // console.log(deleteArr)
    }

    // e <--라는 변수를 사용하고 싶은데, 이벤트가 발생할 때 인자 값이 필요한 경우에만 사용!


    // handleClick = (i) => {
    //     console.log(i)
    //     const a = eventClick = e=> {
    //         console.log(e)
    //     }

    //     return eventClick
    // }

    // this.props.list  배열이 몇개죠 ? 1개
    items = () =>  this.props.list.map((v,k)=>{
        return (
            <ul className="comment-row" key={k}>
                <li className="comment-id">{v.userid}</li>
                <li className="comment-content">
                    {
                        // v.updateflag
                        this.state.update === k
                        ? <input type="text" value={this.state.value} className="comment-update-input"
                        onChange={this.updateChange} onKeyDown={this.updateKeyDown(k)}/>
                        : <span onClick={this.handleClick(k)}>{v.content}</span>
                    }
                    <span className="comment-delete-btn" onClick={()=>{this.deleteClick(k)}}>
                        X
                    </span>
                    
                </li>
                <li className="comment-date">{v.date}</li>
            </ul>
        )
    })

    render(){  
        // 랜더 함수 안의 code는 적게 쓰는 것이 좋다.
        return(
            <li>
                {this.items()}
            </li>
        )
    }
}

export default CommentList
728x90