티스토리 뷰

목차

더보기

강의목차

3-1. import와 require 비교
3-2. 리액트 반복문(map)
3-3. 리액트 반복문(key)
3-4. 컴포넌트 분리와 props
3-5. 주석과 메서드 바인딩
3-6. 숫자야구 만들기
3-7. Q&A
3-8. 숫자야구 Hooks로 전환하기
3-9. React Devtools
3-10. shouldComponentUpdate
3-11. PureComponent와 React.memo
3-12. React.createRef
3-13. props와 state 연결하기

 

3-2. 리액트 반복문(map)

깃 링크: https://github.com/Harimad/zeroReact/commit/cddffeb4f4406d4952bf151a027a137a3f3e66a6


코드 초기 세팅

import React, { Component } from 'react'

function getNumbers() { //숫자 4개 중복없이 랜덤으로 뽑는 함수

}

class NumberBaseball extends Component {
  state = {
    result: '',
    value: '',
    answer: getNumbers(),
    tries: [],
  }
  onSubmitForm = () => {

  }
  onChangeInput = () => {

  }

  render() {
    return(
      <>
        <h1>{this.state.result}</h1>
        <form onSubmit={this.onSUbmitForm}>
        <input maxLength={4} value={this.state.value} onChange={this.onChangeInput}/>
        </form>
        <div>시도: {this.state.tries.length}</div>
        <ul>
        {
          ['1', '2', '3', '4', '5'].map((item) => { //map메서드로 li태그를 찍어낼 예정
            return <li>{item}</li>
          })
        }
        </ul>
      </>
    )
  }
}

export default NumberBaseball

 

map메서드로 li 태그 생성


Q1. 기존까지 빌드를 했을 때는 dist 폴더에 app.js 를 생성해서 빌드가 되었음을 눈으로 확인할 수 있었는데, 핫 리로딩을 하고 개발용서버를 통해 빌드를 한 시점부터 app.js 를 눈으로 확인할 수 없는데도 잘 작동이 되고 있어서 확인해본 결과 메모리 상에서 실행된다고 하는데  왜 그렇게 되는지 궁금합니다!

-> 네 맞습니다. 메모리 상에서 dist/app.js가 존재합니다. 그래서 실제 파일에는 없더라도 웹팩데브서버는 있는 걸로 칩니다.

Q1-2. 그렇다면 배포할 때도 이런 방식으로 사용하는 건가요?
아니면 빌드된 파일을 만들어서 사용하는 방식으로 사용을 하나요?
webpack dev server 개발용 서버라고 하셨는데 그렇다면 실제로 빌드된 파일을 통해 서버에 업로드 되어야 하는게 아닌가 생각이 들어서 질문 드립니다.

-> 배포시에는 실제 파일을 만들어서 합니다 

 

3-3. 리액트 반복문(key)

깃 링크: https://github.com/Harimad/zeroReact/commit/1e61c2f3bcf747469ca5c23c94edc24b04586064


React에서 반복문 사용하는 방법

<ul>
    {
        [  // 배열을 이용한 map 메서드
            ['배열Apple', 'Good'],
            ['배열Banana', 'Bad'],
            ['배열Tangerine', 'sour'],
            ['배열Grape', 'bitter']
        ].map((item, i) => {
            return <li key={item[0]+item[1]}>{item[0]} - {item[1]} -{i}</li>
        })
    }
    {
        [ // 객체를 이용한 map 메서드 (객체를 많이사용함)
            {fruit: '객체Apple', taste: 'Good'},
            {fruit: '객체Banana', taste: 'Bad'},
            {fruit: '객체Tangerine', taste: 'sour'},
            {fruit: '객체Grape', taste: 'bitter'},
        ].map((item, i) => {
            return <li key={item.fruit+item.taste}>{item.fruit}-{item.taste}-{i}</li>
        })
    }
	//노다가형태
    <li><b>일반Apple</b> - Good</li>
    <li><b>일반Banana</b> - Bad</li>
    <li><b>일반Tangerine</b> - sour</li>
    <li><b>일반Grape</b> - bitter</li>
</ul>

배열, 객체를 map메서드로 li출력 + 노가다형태로 li출력

map메서드를 쓸때 key값은 i값을 바로 넣어주면 안된다. 나중에 key값이 중복될 가능성이 있다.

해결방법: uuid로 해도 되고 https://github.com/ai/nanoid/  같이 충돌 확률 적은 친구들 쓰면됨

 

 

3-4. 컴포넌트 분리와 props

깃 링크: https://github.com/Harimad/zeroReact/commit/ebea5720f7079b6fa566ebbc6570be516cfc22d9


1. 속성을 
HTML 에서는 attribute
React 에서는 props 라고 부른다

 

2. 반복문(map) 단위로 코드분리를 많이한다.

 

3.

처음 입문자는 한 컴포넌트에 몰아서 다 적기(top down 형식 - 초보자용)

그리고 학습해나가면서 컴포넌트를 분리해주기(bottom up형식 - 이건 처음부터 하기 어려움)

 


코드 흐름

1. 부모 컴포넌트의 배열값으로 반복문을 돌리기 위해 map 메서드사용

2. Try 자식컴포넌트안에 props값을 넣어줌

3. Try.jsx 파일에서 props 값을 아래 4번 처럼 작성한다.

4. return 문 안에서 4번에 작성한 값을 사용한다.

-> map메서드를 쓰고 props를 쓰면 코드 재생산성이 좋아지고 유지보수가 쉬워진다.

이유는 현업에서는 100줄짜리 코드를 부모컴포넌트에 1줄로 쓸 수도 있기 때문이다.

//NumberBaseball. jsx 파일
class NumberBaseball extends Component {
  fruits = [				// 1
    ['배열Apple', 'Good'],
    ['배열Banana', 'Bad'],
    ['배열Tangerine', 'sour'],
    ['배열Grape', 'bitter'],
  ]
  
  render() {
    return (
        <ul>
          {this.fruits.map((fruit, i) => (	//2
              <Try key={fruit[0]+fruit[1]} fruit={fruit} idx={i} />	//3
            ))}
        </ul>)}
}

//Try.jsx 파일
class Try extends Component {
  render() {
    const { fruit, idx } = this.props	//4
    return (				//5
      <li>
        <div>{fruit[0]}</div>
        <div>{fruit[1]}</div>
        <div>{idx}</div>
        <div>컨텐츠1</div>
        <div>컨텐츠2</div>
        <hr></hr>
      </li>
    )
  }
}

실행결과


참고: https://react.vlpt.us/basic/24-class-component.html

 

24. 클래스형 컴포넌트 · GitBook

24. 클래스형 컴포넌트 이제는 잘 사용하지 않지만, 그래도 클래스형 컴포넌트에 대해서 알아봅시다! 앞으로 이 강의에서 클래스형 컴포넌트를 사용하는 일은 거의 없겠지만 그래도 알아둘 필요

react.vlpt.us


Q. 리액트에서 함수도 분리 가능한지 궁금합니다.
-> 함수는 보통 내부에 this를 쓰는 경우가 많아 분리하지 못하는 경우가 많습니다.

Q. 리액트에서 스타일 작업을 할때는 기존에 html에 css를 link 걸었던 방식대로 하면 될까요? 
-> 스타일 작업도 기존 html과 다릅니다. 물론 css에 클래스를 걸어 쓰는 방법도 쓸 수 있긴 하지만 
리액트에는 css 모듈이나 styled-components를 더 많이 씁니다.

 

3-5. 주석과 메서드 바인딩(this)

깃 링크: https://github.com/Harimad/zeroReact/commit/50d7e6b462eddc0e9d0c451cc5fb9318b3a0550d


🎁🎁1. class 안에서 함수종류(선언적, 화살표)에 따른 this의 의미
화살표 함수를 쓰면 this키워드를 쓸 수 있다. 여기서 this는 화살표 밖의 class를 뜻한다.
하지만, 선언적 함수를 쓰면 this키워드를 쓸 수 없다. 왜냐하면 여기서 this는 방금 만든 함수를 지칭하기 때문이다.

그래도 선언적 함수를 쓰고싶다면 아래 함수를 constructor 생성자 함수안에 함수를 bind해줘야한다.

class NumberBaseball extends Component {
	constructor(props) {
		super(props);
		this.state = {
			value: '';
		}	
        this.onChangeInput1 = this.onChangeInput.bind(this) //이걸 꼭 써야함
	}
	
	onChangeInput1(e) { //선언적 함수 - 생성자 함수 안에서 binding 필수
		console.log(this) // react 내부 출력
	}
    onChangeInput2 = (e) => { //화살표 함수 - 바로 쓸 수 있음(편리)
		console.log(this) // react 내부 출력
	}
}

즉, 화살표 함수가 bind(this)를 자동으로 해주는 셈이다.

 

2. class 안에있는 render() 메서드에서는 화살표 함수를 쓸 필요가 없다.

-> 그건 class 선언 시에 extends Component가 처리를 해주기 때문이다.

 

 

 

3-6. 숫자야구 만들기

깃 링크: https://github.com/Harimad/zeroReact/commit/50666487ea52dad68cefc6e2d1e6138f5327cd00

숫자야구 코드는 여기 들어가서 참고하길... 숫자야구 코드는 JS랑 똑같기 때문에 JS강의 내용을 봐도 무방함.

 


🎁🎁리액트의 동작 원리 - 배열의 값 변화를 기준(기존배열에 바로push VS 새배열 만들고 기존배열 복사)

// 기존 배열에 바로 push 
const array = [];
array.push(1)
console.log(array) // [1]이다

array === array // true -> 리액트曰: 어? 값이 바뀐게 없네? 가만히 있어야지~
// 이렇게 되면 배열에 push를 했지만 리액트는 이전값과 현재값이 바뀐게 없다고 인식한다.

하지만, 리액트에서 이렇게 하면 안된다.

왜? 리액트가 array중에서 무엇이 바뀌었는지 감지를 못한다.

 

그래서 감지할수 있게 하기위해

새로운 변수를 만들어서 기존배열 복사하고 추가할 값을 넣어줘야한다.

const array2 = [...array, 2]
console.log(array2) //[1, 2]
array1 === array2 // false -> 리액트曰: 어? 값이 바뀌었네~ 리랜더링해야지~

왜?

기존array와 새로운array2는 다르기 때문에 감지가 가능하다

리액트가 랜더링하는 기준예전 state(array)와 현재 state(array2)다르면 랜더링을 해준다.


본문적용

아래처럼 바로 state값에 push 하면 안된다. 리액트가 변화 감지 못함.

this.setState( { tries: [this.state.tries.push(this.state.value) ] } )

그래서 새로운 배열을 만들고 기존 배열을 복사해야한다.

this.setState( { tries: [ ...기존배열값, { 새로넣을값 } ] } )

Q. 리액트가 렌더링을 하는 기준이 예전 state랑 현재 state랑 다르면 렌더링을 한다고 하셨는데요. 
 setState만 실행되어도  리렌더링이 된다고하셨는데 

그러면 setState({})안에서 state가 값이 바뀌지 않으면 렌더링 안하는건가요?

 

-> 클래스 컴포넌트에서는 setState만 실행되어도 리렌더링이 되고요.
훅에서는 값이 달라져야지만 리렌더링이 됩니다.
객체는 조심해야할 것이 {} !== {} 이고,  (위에 설명한 배열의 값 변화를 기준 React동작원리와 같음)
참조에서는 항상 true이므로 불변성을 엄격하게 관리하지 않으면 
리렌더링이 뜻대로 안 될 수 있습니다.

3-7. Q&A

깃 링크: https://github.com/Harimad/zeroReact/commit/9ee1d30fb5aafd00273a3e99cef28d9587239ec5

이번작업: 구조분해할당 ex) const { result, value, tries } = this.state;


1. render() 안에 return 부분에서 반복적으로 this.state쓰는게 귀찮다?

render() 메서드 안에 구조분해를 이용하면됨 -> hooks와 비슷해짐

그러면 다른 함수안에 있는 this.state도
구조분해를 똑같이 적용해서 아래 처럼쓰고 this.state를 지워주면 된다.

const { result, value, tries } = this.state;

Try.jsx 파일에서도

props를 구조분해 할당으로 받을 수 있다

const { tryInfo } = this.props;

이렇게 하면 return 부분에 this.props를 지워도 된다.

 

2. getNumbers함수처럼 class 밖에서 쓰는 함수는 어떨때 쓸 수 있나?

-> class 안에서 getNumbers를 this.getNumbers 처럼 쓰는게 없으면 class 밖에 정의할 수 있다.
장점? 밖에 쓴 getNumbers 함수를 다른 데서도 쓸 수 있다.
class 안에 함수를 써놓으면 다른 곳(다른파일)에서 쓸 수 있다.


Q. 이벤트
혹시 'on이벤트이름={~}' 을 태그안에 속성으로 넣을때 react공식문서에 나온 이벤트이름만 쓸수있나요?
아니면 자기가 지은이름지어서 'on내가지은이벤트이름={~}' 이렇게도 넣을수 있나요?

 

-> 커스텀 이벤트는 안 됩니다. 아래 링크 방식 참고하세요.

https://stackoverflow.com/questions/36180414/reactjs-add-custom-event-listener-to-component

 

ReactJS - Add custom event listener to component

In plain old HTML I have the DIV <div class="movie" id="my_movie"> and the following javascript code var myMovie = document.getElementById('my_movie'); myMovie.addEventLi...

stackoverflow.com

Q. 다른데서는 예를들면
<div onCreate={onCreate} onRemove={onRemove}> ~ </div>
이런식으로 공식문서에 검색하면 안나오는 onCreate, onRemove 이런것들을 써넣더라구여..
그래서  이벤트 이름을 저렇게 자기가 임의로 지어도 되는건가 싶어서요..

 

-> 그건 그냥 onCreate라는 prop입니다. 이벤트는 아니고요. 
이벤트처럼 prop을 써서 그런 식으로 이름지은겁니다. 
handleCreate로 짓든 onCreate로 짓든 상관 없습니다.
 이벤트가 아니라 일반 prop이니까요.

 

댓글
다크모드
Document description javascript psychology
더보기 ,제목1 태그 호버