-
[React] Component InteractingFrontend/React 2021. 8. 25. 21:46
Component interacting
React application은 몇 십에서 몇 백 개까지 component를 가질 수 있습니다. 각각의 작은 component들은 자신의 역할을 담당하면서 거대한 app을 구성하고 서로 상호작용함으로써 app을 동작시킵니다.
Component 간 상호 작용 유형
- Component가 다른 component를 렌더링하는 것
- Component가 다른 component에게 정보를 전달하는 것
A component in a render function
class WelshCorgi extends React.Component { render() { return <h1>Welsh Corgi wooooow!</h1>; } } class Dog extends React.Component { render() { return <WelshCorgi />; } }
Component 클래스의
render()
메서드는 HTML-like JSX expression 뿐만 아니라 component instance 형태의 JSX expression도 리턴할 수 있습니다.import React from 'react'; import ReactDOM from 'react-dom'; class WelshCorgi extends React.Component { render() { return <h1>Welsh Corgi wooooow!</h1>; } } class ProfilePage extends React.Component { render() { return ( <div> <h1>All About Me!</h1> <p>I like Welsh Corgi!!!</p> <WelshCorgi /> </div> ); } }
이러한 속성을 활용하면 하나의 component 안에서 다른 여러 개의 component를 함께 렌더링할 수 있습니다. 위의
<WelshCorgi />
component 인스턴스는ProfilePage
component가 생성되면 그 안에서 렌더링됩니다. 따라서,ReactDOM.render()
를 통해ProfilePage
인스턴스 하나만 렌더링하면 내부에 있는 component들은 자동으로 함께 렌더링되게 됩니다.Component 안에 다른 component가 포함되어 렌더링될 수 있다는 특징은 리액트의 강력한 장점입니다!
Props
부모 component가 자식 component에가 전달하는 정보가 담긴 객체를
props
라고 합니다. 모든 component들은 자신의props
를 가지고 있으며, 이를 통해 부모 component로부터 전달받은 정보를 확인할 수 있습니다.특정 component의
props
를 보고 싶다면,this.props
를 사용해 확인할 수 있습니다.<Greeting name="Frarthur" town="Flundon" age={2} haunted={false} myInfo={["top", "secret", "lol"]} />
Component에 prop을 추가하고 싶다면, 생성한 인스턴스에 속성으로 추가해주면 됩니다. 위의 코드는
<Greeting />
component 인스턴스에name
,town
,age
,haunted
,myInfo
등의 props를 부여한 것입니다.이 때 만일 string이 아닌 정보를 주고 싶다면,
{}
로 정보를 감싸서 속성을 부여해야 한다는 점을 유의합시다.이렇게 추가한 속성들은
this.props.속성이름
을 통해 접근할 수 있습니다.Event handler as prop
함수 역시
props
로 넘길 수 있는데, 보통 event handler 함수가 이러한 특징을 활용해 prop으로 자주 전달됩니다.import React from 'react'; import ReactDOM from 'react-dom'; class Button extends React.Component { render() { return ( <button onClick={this.props.talk}> Click me! </button> ); } } class Talker extends React.Component { talk() { let speech = ''; for (let i = 0; i < 10000; i++) { speech += 'blah '; } alert(speech); } render() { return <Button talk={this.talk} />; } } ReactDOM.render( <Talker />, document.getElementById('app') );
Event handler는
render()
메서드와 비슷한 방식으로 임의의 이름의 메서드를 정의하고 필요한 component에 prop으로서 전달합니다.Naming convention of event handler
Event handler를 prop으로 전달할 때, 임의로 naming해야 할 부분이 두 군데 생깁니다. 이 때, 반드시 따를 필요는 없지만 통용되는 naming convention이 존재합니다.
첫 번째는 event handler 메서드를 정의할 때인데, 이벤트의 타입에 따라 handleClick, handleHover 등으로 사용합니다.
두 번째는 prop name인데, 이벤트 타입에 따라 onClick, onHover 등으로 정의합니다.
class MyClass extends React.Component { handleHover() { alert('I am an event handler.'); alert('I will listen for a "hover" event.'); } render() { return <Child onHover={this.handleHover} />; } }
this.props.children
모든 component들은
props
객체 내에children
property를 가집니다. 앞서 self-closing tag로 만들었던 component들은 사실<MyComponentClass></MyComponentClass>
로 나뉘어 쓰이는 것 역시 가능합니다. 이 경우,this.props.children
은 나뉘어 쓰이는 태그 사이에 존재하는 모든 것을 리턴합니다.import React from 'react'; import ReactDOM from 'react-dom'; class List extends React.Component { render() { let titleText = `Favorite ${this.props.type}`; if (this.props.children instanceof Array) { titleText += 's'; } return ( <div> <h1>{titleText}</h1> <ul>{this.props.children}</ul> </div> ); } } class App extends React.Component { render() { return ( <div> <List type='Dog'> <li>Welsh Corgi</li> <li>Dachshund</li> </List> <List type='Cat'> <li>Road cat</li> </List> </div> ); } } ReactDOM.render( <App />, document.getElementById('app') );
위 코드의 경우,
this.props.children
은 각각의 List component 사이에 있는 모든<li>
element들을 리턴합니다.<List type='Dog'>
의 경우
// return elements <li>Welsh Corgi</li> <li>Dachshund</li>
<List type='Cat'>
의 경우
// return element <li>Road cat</li>
defaultProps
class Example extends React.Component { render() { return <h1>{this.props.text}</h1>; } } Example.defaultProps = { text: 'Welsh Corgi' };
만일 component 인스턴스에 요구되어지는 prop이 전달되지 않았을 때, 해당 prop은 화면에 아무것도 출력하지 않을 것입니다. 이 때, default 값을 prop에 지정해 화면에 항상 무언가가 출력될 수 있게 할 수 있습니다.
이를 위해 component 클래스의
defaultProps
property를 사용합니다.defaultProps
property에 원하는props
의 기본값들을 설정한 object를 지정하여 기본값 설정을 완료합니다.state
축구 경기에서 각 팀의 스코어 정보처럼 변할 수 있는 정보를 dynamic information이라고 합니다. 리액트 component는 이러한 dynamic information을 다뤄야 할 때,
props
와state
를 사용합니다. 그 중,state
란 각각의 component가 가지고 있는 상태를 저장한 것을 뜻하며, component 내부에서 관리됩니다. 렌더링 결과물에 영향을 주는 정보를 갖고 있다는 부분에서도props
와 공통점이 있습니다.class Example extends React.Component { constructor(props) { super(props); this.state = { mood: 'decent' }; } render() { return <div></div>; } } <Example />
초기의
state
는props
와 달리 component 클래스의 constructor에서state
property를 지정해 설정합니다. 또한, 각각의 component들은 스스로의state
를 가집니다.모든 component는
super()
를 통해 항상 초기화 시켜야 합니다. 이후,state
에 적절한 객체를 할당해 initial state를 설정합니다.class TodayImFeeling extends React.Component { constructor(props) { super(props); this.state = { mood: 'decent' }; } render() { return ( <h1> I'm feeling {this.state.mood}! </h1> ); } }
Component 클래스 내에서
state
에 접근하고 싶다면this.state.name-of-property
형태로 접근합니다. 위의this.state.mood
는 'decent' 값에 접근합니다.this.setState()
Component의 현재
state
를 바꾸고 싶다면,this.setState()
메서드를 사용합니다.setState()
는 변경 요소가 담긴 객체를 첫 번째 인자로 받아 사용합니다.{ mood: 'great', hungry: false }
현재
state
의 상황이 위와 같다고 가정해봅시다.this.setState({ hungry: true });
그리고
setState()
를 사용해hungry
상태를 변경합니다.{ mood: 'great', hungry: true }
그 결과 위와 같이
hungry
상태만true
로 변경되었습니다.setState
는 기본적으로 인자로 받은 객체에 담긴 요소들만 접근해 값을 변경하고 다른 원래의 요소들은 그대로 둡니다.setState()와 render()
setState()
메서드에서 유의할 점은 이 메서드가state
를 변경한 후 자동적으로.render()
메서드까지 호출한다는 부분입니다. 즉,setState()
를 사용하면state
를 변경한 부분이 바로 화면에 반영됩니다. 따라서,setState()
는render()
메서드 안에서 호출되면 안됩니다. 이를 지키지 않으면 서로 끊임없이 호출하는 무한 루프에 빠지게 됩니다.Reference
'Frontend > React' 카테고리의 다른 글
[React] Advanced Tip (0) 2021.08.25 [React] Hook (0) 2021.08.25 [React] Component Lifecycle Methods (0) 2021.08.25 [React] Component (0) 2021.08.25 [React] JSX (0) 2021.08.25