# 컴포넌트 통신

## 1. 컴포넌트 간 통신이 필요한 이유

React의 클래스 컴포넌트는 캡슐화 되어 있기 때문에 본인의 상태(state)를 가질 수 있어서 관리가 용이하다. 하지만 컴포넌트가 중첩 되었을 때 개별적으로 상태를 관리하는 특징 때문에 상태를 공유하는 것이 까다롭다.&#x20;

{% hint style="info" %}
Ract는 자바 스트립트와 달리 컴포넌트의 상태가 스코프 체인 되지 않는다.&#x20;
{% endhint %}

React 프로그래밍에서는 부모 컴포넌트가 상태를 관리하고, 자손 컴포넌트는 부모 컴포넌트와 통신 하여 상태를 공유 처리한다.&#x20;

## 2. props ⇌ callback

![간단한 컴포넌트 간 통신 ](https://831271375-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MSRg9KgNRIGErVFy_6g%2F-MTLgv0gdGIUmIxt3O6k%2F-MTLx82VKwP7pMCbGn9w%2Fimage.png?alt=media\&token=9472d5a2-d73a-4f2b-b9bf-49e5bfda8ad8)

{% hint style="warning" %}
주의 할 점!&#x20;

* 클래스 컴포넌트에서 이벤트 핸들러를 전달 할 때 클래스 필드 문법을 사용한다면 아래와 같이 사용하기! 아직 익숙하지 않아서 계속 잊어버린다! 기억하기!!&#x20;
  {% endhint %}

{% tabs %}
{% tab title="부모 컴포넌트 Lecturer.js " %}

```javascript
import React, { Component } from 'react'
import PropsTypes from 'prop-types'
import Lecture from './Lecture'

class Lecturer extends Component {
  static propTypes = {
    instructor: PropsTypes.array,
  }

  static defaultProps = {
    instructor: [],
  }

  parentComponentMethod = () => {
    console.log('부모 컴포넌트에 콜백 됨')
  }

  render() {
    return (
      <ul className="lecturers">
        {this.props.instructor.map((lecturer) => (
          <Lecture
            key={lecturer.id}
            lecturer={lecturer}
            // onParentCallback이란 이름으로 Lecture(자식) 컴포넌트에 속성을 보냄
            onParentCallback={this.parentComponentMethod}
          >
            <figure className="lecturer-info">
              <img src={lecturer.image} alt="" className="lecturer-photo" />
              <figcaption>
                {lecturer.module} 모듈을 담당 할 {lecturer.name} 강사 Facebook
                바로가기
              </figcaption>
            </figure>
          </Lecture>
        ))}
      </ul>
    )
  }
}

export default Lecturer

```

{% endtab %}

{% tab title="자식 컴포넌트 Lecture.js " %}

```javascript
import React from 'react'

// onParentCallback 속성을 받아 옴
const Lecture = ({ lecturer, children, onParentCallback }) => (
  <li className="lecturers">
    <a href={lecturer.facebook} rel="noreferer nopener">
      {children}
    </a>
    <button
      type="button"
      className="button-remove-lecturer"
      // 받아온 onParentCallback을 버튼에 이벤트 바인딩
      onClick={onParentCallback}
    >
      제거
    </button>
  </li>
)

export default Lecture

```

{% endtab %}
{% endtabs %}

![](https://831271375-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MSRg9KgNRIGErVFy_6g%2F-MT8AfAT3lkyS0e5yXDf%2F-MT8Pl-78s4pv-SIjWW0%2Fimage.png?alt=media\&token=b6a5d01e-079c-4b91-8b01-976ef1fcab92)

### 2.1 부모 ➡︎ 자식 (메서드 전달) <a href="#undefined" id="undefined"></a>

```javascript
class Lecturer extends React.Component {
  parentComponentMethood = () => {
    console.log('부모 컴포넌트에 콜백 됨')
  }

  render() {
    return (
      <ul className="lecturers">
        {this.props.instructor.map((lecturer) => (
          <Lecture
            key={lecturer.id}
            lecturer={lecturer}
            onParentCallback={this.parentComponentMethood}
          >
            <figure className="lecturer-info">
              <img src={lecturer.image} alt="" className="lecturer-photo" />
              <figcaption>
                {lecturer.module} 모듈을 담당 할 {lecturer.name} 강사 Facebook
                바로가기
              </figcaption>
            </figure>
          </Lecture>
        ))}
      </ul>
    )
  }
}
```

### &#x20;2.2 부모 ⬅︎ 자식 (메서드 실행) <a href="#undefined" id="undefined"></a>

```javascript
const Lecture = ({ lecturer, children, onParentCallback }) => (
  <li className="lecturers">
    <a href={lecturer.facebook} rel="noreferer nopener">
      {children}
    </a>
    <button
      type="button"
      className="button-remove-lecturer"
      // 받아온 onParentCallback을 버튼에 이벤트 바인딩  
      onClick={onParentCallback}
    >
      제거
    </button>
  </li>
)
```

## 3. 복잡한 컴포넌트 트리 구조

{% embed url="<https://codesandbox.io/s/intelligent-yonath-l9ml0?fontsize=10&hidenavigation=1&theme=dark&view=editor>" %}
복잡한 컴포넌트 트리 구조&#x20;
{% endembed %}

{% hint style="warning" %}
주의하기!&#x20;

* Lecturers에서 App에서 받아온 props의 이벤트 함수에 접근할 때, `this.props.removeLecturer`으로 접근해야 한다. 다시 해석하면 **"클래스(인스턴스)의 부모컴포넌트에서 전달받은 속성(props)중에서 removeLecturer 함수"**&#xC5D0; 접근한다.

```javascript
handleRemoveLecturer={this.props.handleRemoveLecturer}
```

* 앞서 배운 것 처럼 이벤트 함수에 특정 인자를 전달 할 때, 화살표 함수 또는 `bind()` 사용하기! 만약 사용하지 않는다면 이벤트가 발생하기 전에 함수가 실행된다.&#x20;

```javascript
onClick={() => handleRemoveLecturer(lecturer.id)}
```

* `setState()`를 사용해서 상태 업데이트 하는거 계속 잊어버린다. 조심하기!&#x20;

```javascript
this.setState({
      FEML_lecturers: filteredLecturers,
    })
```

{% endhint %}

## 참고&#x20;

* [React 끌어올리기 ](https://ko.reactjs.org/docs/lifting-state-up.html#lifting-state-up)
