일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 스노쿨링
- 삼성무선청소기제트
- autocomplate
- 사기
- 자동완성
- plugin
- Webpack
- 정직하게사세요
- Hooks
- REACT
- 특수문자
- 막탄
- 맛사지
- 중고나라사기
- ES6
- 유효성검사
- 중고나라
- js
- 스쿠버다이빙
- 마사지
- 네이버페이사기
- 해외여행
- 중고거래사기
- JavaScript
- webpack.config.js
- 정규식
- 세부
- 구분
- 여행
- Today
- Total
Ryu.log
[ React-Tutorial-04 ] props와 state 본문
01. 새 Component 만들기
// MyName.js import React, { Component } from 'react'; class MyName extends Component { render() { return ( <div> 안녕하소! <b>{this.props.name}</b> 입니다~ </div> ); } } export default MyName;
자신이 받아온 props 값은 this. 키워드를 통하여 조회할 수 있다.
현재 name 이라는 props를 보여주도록 설정해 두었다. 그럼 이제 이 Component를 사용해 보자.
App.js를 열고 아래와같이 작성해보자.
mport React, { Component } from 'react'; import MyName from './MyName'; class App extends Component { render() { return ( <MyName name="이수근" /> ); } } export default App;
import를 통하여 Component를 불러오고 랜더링을 한다. 이렇게 Component를 만들고 나면, 일반 테그를 작성 하듯이 작성해주면 된다.
그리고 props 값은 name="이수근" 이런식으로 테그에 속성(attrbute 값)을 설정해주는 것 처럼 해주면 된다.
작성을 완료 한 뒤, 브라우저 확인을 해보면 아래와 같은 결과가 나온다.
02. defaultProps
// MyName.js import React, { Component } from 'react'; class MyName extends Component { static defaultProps = { name: '1577' } render() { return ( <div> 안녕하소! <b>{this.props.name}</b> 입니다~ </div> ); } } export default MyName;
이렇게 MyName. Component의 코드를 고쳐 놓은 뒤, App.js에서 <MyName /> 이런식으로 뒤에 name값을 생략해버리면 "1577"이 default 값으로 들어가게 될것이다.
defaultProps는 아래와 같은 형태로도 설정 가능하다.
import React, { Component } from 'react'; class MyName extends Component { render() { return ( <div> 안녕하소! <b>{this.props.name}</b> 입니다~ </div> ); } } MyName.defaultProps = { name: '1577' }; export default MyName;
바로 다음에 알아볼 함수형 Component에서 defaultProps를 설정할땐 위 방식으로 하면 된다.
03. 함수형 Component
import React from 'react'; const MyName = ({ name }) => { return ( <div> 안녕하소! {name} 입니다~ </div> ); }; export default MyName;
훨씬 간단하다. 함수형 Component와 클래스형 Component의 주요 차이점은, 조만간 진행할 state와 LifeCycle 이 빠져있다는 점이다.
그래서 Component 초기 마운트가 아주 미세하게 빠르고, 메모리 자원을 덜 사용한다. 미세한 차이이니, Component를 무수히 많이 렌더링 하게 되는게 아니라면
성능 이슈는 없다.
04. state
import React, { Component } from 'react'; class Counter extends Component { state = { number: 0 } handleIncrease = () => { this.setState({ number: this.state.number + 1 }); } handleDecrease = () => { this.setState({ number: this.state.number - 1 }); } render() { return ( <div> <h1>Counter</h1> <div>Result: {this.state.number}</div> <button onClick={this.handleIncrease}>+</button> <button onClick={this.handleDecrease}>-</button> </div> ); } } export default Counter;
위에서부터 아래로 쭉 살펴보면 우선 Component의 state를 정의할 때는 class fields 문법을 사용해서 정의한다.
만약 class fields 문법을 사용하지 않는다면 아래와 같이 사용한다.
import React, { Component } from 'react'; class Counter extends Component { constructor(props) { super(props); this.state = { number: 0 } } ... }
class fields 를 사용하는 이유는 편의를 위함이다. 확실히 constructor에 넣어서 사용하는 것보다 편해보인다.
위 코드의 constructor 에서 super(props)를 호출 한 이유는, Component를 만들게 되면서, React Component를 상속했으며,
constructor를 작성하게 되면 기존( React Component ) 클래스의 생성자를 덮어쓰게 된다.
그렇기에, React Component가 지니고 있던 생성자를 super를 통하여 미리 실행하고,
그 다음에 우리가 작업할(state 설정)을 해주는 것이다.
그렇다면, class fields와 constructor 둘 다 사용하게 되면, 어떤부분이 더욱 늦게 설정 될까?
class fields가 먼저 실행되고, 그 뒤에 constructor에서 설정된 것들이 나오게 된다.
05. 메소드 작성
handleIncrease = () => { this.setState({ number: this.state.number + 1 }); } handleDecrease = () => { this.setState({ number: this.state.number - 1 }); }
Component에 메소드를 작성해 주었다. Component에서 메소드는 아래와 같은 형식으로도 작성 될 수 있다.
handleIncrease() { this.setState({ number: this.state.number + 1 }); } handleDecrease() { this.setState({ number: this.state.number - 1 }); }
이렇게 하면, 나중에 버튼에서 Click Event가 발생 했을 때, this 가 undefind로 나타나서 제대로 처리되지 않게 된다.
이는 함수가 버튼의 Click Event로 전달이 되는 과정에서 "this"와의 연결이 끊겨버리기 때문인데, 이를 고쳐주려면 constructor 에서
constructor(props) { super(props); this.handleIncrease = this.handleIncrease.bind(this); this.handleDecrease = this.handleDecrease.bind(this); }
위와 같이 해주거나, 이전에 작성한 코드처럼 아에 arrow function 형태로 하면 this가 풀리는 것에 대해 걱정할게 없다.
06. setState
state = { number: 0, foo: 'bar' }
this.setState({ number:1 });을 하게 되면, foo 는 그대로 남고, number 값만 업데이트 된다.
setState는 객체의 깊숙한 곳까지 확인하지 못한다. 예를 들어서, state가 다음과 같이 설정되어있다고 가정한다면,
state = { number: 0, foo: { bar: 0, foobar: 1 } }
아래와 같이 한다고 해서 foobar 값이 업데이트 되지 않는다.
{ number: 0, foo: { foobar: 2 } }
그 대신에 위와같은 상황에서는 아래와 같이 해주어야 한다.
this.setState({ number: 0, foo: { ...this.state.foo, foobar: 2 } });
...은 JavaScript의 전개연산자 이다. 기존 객체안에 있는 내용을 해당 위치에다가 풀어준다는 의미이다. 그 뒤에, 설정하고 싶은 값을 또넣게 되면 해당값을 덮어쓰게 된다.
07. setState에 객체 대신 함수 전달하기
this.setState({ number: this.state.number + 1 });
큰 문제는 아니지만, 굳이 또 this.state를 조회해야 하는데, 아래와 같이하면 좀더 멋진 문법으로 작성 할 수 있다.
this.setState( (state) => ({ number: state.number }) );
setState에 updater 함수를 만들어서 전달해 주었다. 여기서 조금더 나아가면 이렇게 작성될 수 있다.
this.setState( ({ number }) => ({ number: number + 1 }) );
자세히 보면 (state)가 ({number}) 로 변했다 이것은 비구조화 할당 이라는 문법이다.
이 문법은 아래와 같이도 사용 할 수 있다.
const { number } = this.state;
결국 코드를 조금 덜 작성하고 싶다면 이렇게도 할 수 있다.
const { number } = this.state; this.setState({ number: number + 1 })
마음에 드는 코드 중 아무거나 사용하면 된다.
그렇다면 기존에 작성했던 함수를 각각 다른 방식으로 구현해보자.
handleIncrease = () => { const { number } = this.state; this.setState({ number: number + 1 }); } handleDecrease = () => { this.setState( ({ number }) => ({ number: number - 1 }) ); }
08. 이벤트 설정
render 함수에서 이벤트 설정을 한 부분을 확인해보자.
render() { return ( <div> <h1>카운터</h1> <div>값: {this.state.number}</div> <button onClick={this.handleIncrease}>+</button> <button onClick={this.handleDecrease}>-</button> </div> ); }
버튼이 클릭되면 준비한 메소드 함수가 각각 호출되도록 설정해주었다. 기존에 JavaScript로 비슷한 작업을 해봤다면 아래 코드가 익숙 할 것이다.
<button onclick="alert('hello');">Click Me</button>
html에서는 onclick 속성에 클릭되면 실행 할 JavaScript를 문자열 형태로 넣어준다. 반면에 우리가 작성한 코드를 다시보면
<button onClick={this.handleIncrease}>+</button>
여기서 정말 주의 해야 할 것은, React 에서 이벤트 함수를 설정할 때 html과 아래와 같은 사항이 다르다.
- 이벤트 이름을 설정 할 때 camelCase 로 설정해 주어야 한다. onclick은 onClick, onmousedown은 onMouseDown, onchange는 onChange 이런식으로 말이다.
- 이벤트에 전달해주는 값은 함수여야 한다. 만약에 onClick={this.handleIncrease()} 이런식으로 하게 된다면, 렌더링을 할 때마다 해당 함수가 호출이 된다.
그렇게 된다면 정말 큰일이 발생한다. 렌더링 > 함수호출 > setstate > 렌더링 > 함수호출 > 무한반복... 이렇게 되어버리는 것이다.
그래서 꼭 주의해야 한다. 렌더링 함수에서 이벤트를 설정할 때 우리가 만든 메소드를 호출하면 안된다.
모든 설명이 끝났고 Counter Component를 App.js에 불러와서 랜더링해보면
import React, { Component } from 'react'; import MyName from './MyName'; import Counter from './Counter'; class App extends Component { render() { return ( <fragment> <MyName name="이수근"/> <Counter /> </fragment> ); } } export default App;
아래에 있는 버튼들을 눌러보면 숫자가 바뀐다!
이 글은 Velopert님의 블로그에서 React 포스팅을보며 실습하며 공부한 자료입니다.
'Prev-content' 카테고리의 다른 글
[ React-Tutorial-06 ] input 상태관리 (0) | 2018.05.30 |
---|---|
[ React-Tutorial-05 ] LifeCycle API (0) | 2018.05.28 |
[ React-Tutorial-03 ] JSX (0) | 2018.05.25 |
[ React-Tutorial-02 ] React 프로젝트 시작 (0) | 2018.05.24 |
[ React-Tutorial-01 ] React 란? (0) | 2018.05.24 |