자라선

(React & Express 를 이용한 웹 어플리케이션 개발하기) 6일차 - 선택 조회 본문

Develop/React

(React & Express 를 이용한 웹 어플리케이션 개발하기) 6일차 - 선택 조회

자라선 2021. 1. 20. 22:58

www.inflearn.com/course/react-%EA%B0%95%EC%A2%8C-velopert/lecture/4151?tab=curriculum


 

import React from 'react';
import ContactInfo from './ContactInfo';
import ContactDetails from './ContactDetails';

export default class Contact extends React.Component {
    
    // 생성자에게 state를 생성하지만 react-hot-loader를 사용할때 
    // constructor를 재실행해주진 않는다.(새로고침해야함)
    constructor(props) {
        super(props);
        this.state = {
            selectedKey: -1,
            // 검색에 사용될 state를 정의
            keyword: '',

            // 검색될 리스트
            contactData: [{
                name: 'Abet',
                phone: '010-0000-0001'
            }, {
                name: 'Betty',
                phone: '010-0000-0002'
            }, {
                name: 'Charlie',
                phone: '010-0000-0003'
            }, {
                name: 'David',
                phone: '010-0000-0004'
            }]
        };

        // 생성된 메소드에 this를 바인딩한다.
        this.handleChange = this.handleChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
    }

    // input에서 변경될때 마다 메소드의 이벤트를 실행해준다.
    handleChange(e){
        // 검색되는 값으로 keyword state 값을 변경해준다.
        this.setState({
            keyword: e.target.value
        });
    }

    // key값을 넘겨받아 selectedKey의 값을 갱신해주며 콘솔에 출력한다.
    handleClick(key){
        this.setState({
            selectedKey: key
        });

        console.log(key, 'is selected');
    }

    render() {
        // 리스트에 뿌려줄 함수
        const mapToComponents = (data) => {

            // sort를 사용하여 리스트를 정렬해준다(유니코드)
            data.sort();

            // 리스트를 필터로 하여 입력된 값에 맞도록 %value%의 값만 찾아서 새로운 배열로 만들어준다.
            // toLowerCase 로 리스트의 name 값과 입력되는 input값을 서로 동일한 소문자 조건으로 비교해준다.
            // -1 초과 라는 뜻은 값이 1 or 0 라는 뜻이다.
            data = data.filter((contact) => {
                return contact.name.toLowerCase().indexOf(this.state.keyword.toLocaleLowerCase()) > -1;
            });

            // onClick은 이벤트의 역할이 아닌 props의 값을 전닳해주는 용도로 적용된다.
            return data.map((contact, i) => {
                return (<ContactInfo 
                            contact={contact} 
                            key={i}
                            onClick={()=>{this.handleClick(i)}}/>);
            });
        };
        
        return (
            <div>
                <h1>Contacts</h1>
                <input 
                    name="keyword" 
                    placeholder="Search"
                    value={this.state.keyword}
                    onChange={this.handleChange} />

                <div>{mapToComponents(this.state.contactData)}</div>
                
                {/* 
                    처음 로드시 선택되지 않았다면 -1의 값이 오게된다.
                    리스트를 선택하게된다면 selectedKey에는 handleClick에 의해 key값이 들어가게된다.
                 */}
                <ContactDetails isSelected={this.state.selectedKey != -1}
                                contact={this.state.contactData[this.state.selectedKey]}/>
            </div>
        );
    }
}

선택시 상세한 contact 내용을 조회하기 위해 추가.

selectedKey라는 state의 객체를 생성하여 기본값은 -1로 지정.

 

import React from 'react';

export default class ContactInfo extends React.Component {
    render() {
        // div의 ocClick 이벤트의 function을 props로 넘겨받는다.
        return (
            <div onClick={this.props.onClick}>{this.props.contact.name} {this.props.contact.phone}</div>
        );
    }
}

handleClick 메소드를 만들어 ContactInfo 컴포넌트에 props로 메소드를 넘겨서 onClick에 적용하여 랜더링한다.

 

import React from 'react';

export default class ContactDetails extends React.Component{

    render(){

        // JSX를 변수로 저장한다.
        const detail = (
            <div>
                <p>{this.props.contact.name}</p>
                <p>{this.props.contact.phone}</p>
            </div>
        );
        const blank = (
            <div>
                Not Selected
            </div>
        );

        // props의 boolean의 참, 거짓 여부에 따라 JSX를 가져온다.
        return (
            <div>
                <h2>Details</h2>
                {this.props.isSelected ? detail : blank}
            </div>
        );
    }
}

// props의 값이 없는경우 비어있는 contact 값을 기본으로 설정
ContactDetails.defaultProps ={
    contact:{
        name: '',
        phone: ''
    }
}

동일한 폴더에 ContactDetails 컴포넌트를 만들어 contact 객체 props를 넘겨받아 JSX로 랜더링 시켜주어 반환해주도록 설정

 

혹시 props의 값을 전달받지 못한경우(첫 로드시 선택되지않았기 때문에 props의 값을 전달받지 못하여 에러뜸)

defaultProps의 값을 명시적으로 지정해준다.

 

 

Comments