본문 바로가기
Programming/Javascript

React강좌2, 전화번호부 - 2.Detail 보기 기능

by Wilkyway 2020. 8. 1.
반응형

1. ContactInfo 컴포넌트에서 phone 번호를 삭제하고, Click 이벤트를 연결합니다.

ContactInfo.js

import React, { Component } from 'react';

export default class ContactInfo extends React.Component {
    render() {
        return (
            <div onClick={this.props.onClick}>{this.props.contact.name}</div>   // onClick 을 Props로 받음
        );
    }
}

2. Contact 컴포넌트에서 onClick 이벤트에 해당하는 연결함수(handleClick)를 선언하고, <ContactInfo> 컴포넌트 내부에서 연결해줍니다. handleClick(i) 함수에서는 selectedKey 변수에 몇번째 요소인지(i)를 나타내는 key를 할당합니다. 그리고 기존 화면 요소에 추가로 ContactDetails 컴포넌트를 작성하여 화면에 렌더링합니다. 

ContactDetails 컴포넌트의 내부 props로는 isSelected와 contact를 선언하여 사용할 준비를 합니다.

Contact.js

import React, { Component } from 'react';
import ContactInfo from './ContactInfo';
import ContactDetails from './contactDetails';

export default class Contact extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            selectedKey: -1,
            keyword: '',
            contactData: [{
                name: 'Abet',
                phone: '010-000-001'
            }, {
                name: 'Betty',
                phone: '010-000-002'
            }, {
                name: 'Charlie',
                phone: '010-000-003'
            }, {
                name: 'David',
                phone: '010-000-004'
            }]
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
    }

    handleChange(e) {
        this.setState({
            keyword: e.target.value
        })
    }

    handleClick(key) {
        this.setState({
            selectedKey: key
        });
        console.log(key, 'is selected');
    }

    render() {
        const mapToComponents = (data) => {     // 배열형 data 받아들임
            data.sort();    // 오름차순정렬
            data = data.filter((_contact) => {
                return _contact.name.toLowerCase().indexOf(this.state.keyword.toLowerCase()) > -1;   // contact 배열에서 keyword를 포함하는(indexOf) 요소를 찾아서(-1 보다 큰..) 반환 (모두 소문자로 변환하여 비교)
            })
            return data.map((_contact, i) => {   // 배열의 1개 원소 _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>
                <ContactDetails
                    isSelected={this.state.selectedKey != -1} // selectedKey가 -1이 아니면 참을 전달 
                    contact={this.state.contactData[this.state.selectedKey]}
                />
            </div>
        );
    }
}

 

3. 화면에 추가할 ContactDetails를 작성합니다. 특정인이 선택되었을 때 표시할 details 변수와 아무도 선택되지 않았을 때 나타낼 blank변수를 선언합니다. 그리고 props로 넘겨받은 isSelected가 true이면 details, false면 blank를 그리도록 작성합니다. 그리고 props로 전달받는 contact의 name과 phone의 초기값은 공란('')으로 정의해둡니다.

ContactDetails.js

import React from 'react';

export default class ContactDetails extends React.Component {
    render() {

        const details = (	//특정인이 선택되었을 때 표시할 화면요소
            <div>
                <p>{this.props.contact.name}</p>
                <p>{this.props.contact.phone}</p>
            </div>
        );
        const blank = (<div>Not Selected</div>); //아무도 선택되지 않았을 때 표시할 화면요소
        return (
            <div>
                <h2>Details</h2>
                {this.props.isSelected ? details : blank}
            </div>
        )
    }
}

ContactDetails.defaultProps = {
    contact: {
        name: '',
        phone: ''
    }
};
반응형

댓글