J2KB 리액트 공부_2주차

낭만개발자·2021년 11월 6일
2

J2KB React입문

목록 보기
1/2

노마드 코더 & react API 내용

useEffect는 단 한번 실행.

강의 코드 타이핑함. 내 레파지토리임
https://github.com/heedaelee/nomadLecture

2021ver 6강 까지 강의 타이핑 중단.
React Api 문서로 이동

ReactApi

Quick Start

JSX 인젝션 공격 예방 가능

const element = <h1>{title}</h1>

React DOM은 기본적으로 렌더링 되기 전에 JSX 내에 포함된 모든 값을 이스케이프 한다 (이스케이프 : html 태그로 해석 하지 못하게 걍 문자로 표현하게 하는것, html태그 탈출한다고 생각하면 편함) 이스케이프 되니깐 XSS(cross-site-scripting) 공격을 막을 수가 있다.

React 라이프 사이클

constructor

자바 같은 언어를 써봤다면 들어봤을 만한 constructor(생성자)이다. 이것은 자바와 마찬가지로 컴포넌트를 만들 때 처음으로 실행된다. 이 메서드에서는 초기 state를 정할 수 있다.

render

클래스 컴포넌트에서 반드시 구현돼야하는 유일한 메서드

👀 shouldComponentUpdate가 false이면 실행되지 않는다! 컴포넌트의 props나 state를 활용하여 아래 것 중 하나를 반환하는 역할

componentDidMount

컴포넌트를 만들고 첫 렌더링을 마친 후 실행

  • 마운트란?
    • 끼우다, 고정하다, 올라타다 등의 사전적 의미
    • 리액트에서는 컴포넌트를 특정 영역에 끼워넣는 행위를 가리킨다.
    • 예로 ReactDOM.render 함수를 통해서 DOM의 특정 영역에 리액트 컴포넌트를 끼워 넣을 수 있고, 이러한 과정을 마운트한다고 의미한다.

componentDidUpdate

이것은 리렌더링을 완료한 후 실행한다. 업데이트가 끝난 직후이므로, DOM관련 처리를 해도 무방하다.

componentWillUnmount

이것은 리렌더링을 완료한 후 실행한다. 업데이트가 끝난 직후이므로, DOM관련 처리를 해도 무방하다.
(= hook의 useEffect(()=> {return 여기 부분}) 과 같다고 보면 된다. useEffect 함수의 return 부분이 언마운트 되기 전에 보통 sideEffect을 제거한다? 거나 input 값 초기화 하는 작업을 하는데 같은 기능이다)

리스트와 key

키는 React가 어떤 아이템이 바뀌었는지, 추가됬는지, 삭제됬는지 인식하는데 도움을 줌.
대부분의 경우 데이터의 ID를 키로 함.

여러개의 input 요소를 제어해야할 때 각 요소에 name 속성을 추가한 후 event.target.name 값을 기반으로 핸들러 함수를 고를 수 있습니다.

import React, { Component } from "react";

export default class Reservation extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGusets: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;

    //요거 유용하게 쓰임
    //이런식으로 [name]에 사용하는게 좀 낯설고 첨본 사람도 있을텐데
    //이렇게 사용하면 어떤 점이 좋냐면
    //지금 구조상 const name 이 "isGoing" 일수도
    //"numberOfGuests"일수도 있다. 그래서 name = 'isGoing' 이라면
    // isGoing: value로 취급되어 위에 생성자내에 this.state의 
    //isGoing값이 바뀔꺼고
    // name='numberOfGuests'이라면 numberOfGuests:value 취급되어
    //생성자 내에 this.state의 numberOfGuests 값이 바뀔것이다.
    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange}
          />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            checked={this.state.numberOfGusets}
            onChange={this.handleInputChange}
          />
        </label>
      </form>
    );
  }
}

주어진 input 이름에 해당하는 state 키를 업데이트하기 위해 ES6 computed property name 구문을 사용하고 있습니다.

this.setState({
  [name]: value
});

Facebook과 Instagram도 React를 사용했다.. React가 향후 5년동안 프론트를 지배할것이다!!!아마 그럴것이다!!

React 스럽게 생각하기

테이블을 만들때 어떻게 해야 React 스럽게 생각하는 걸까?

1단계: UI를 컴포넌트 계층으로 분리하기

컴포넌트는 단일 책임 원칙 (single reponsiblity principle)을 지켜야 한다.
1가지 job만 하는것.
대강 페이지를 그림 그려서 조각 내라 이말임.

이 그림을 보면 알수 있는데, 보통 가장 큰 컴포넌트 흔히 container 라 하는게 기본으로 들어가고, 그담 보면 search 부분이 있는데 파란색 사각형 부분은 다른부분과 공통됨이 없이 유니크하므로 1개 컴포넌트로 보고, 아래것도 크게 1개로 봐서 상,하 이렇게 쪼갤수 있다. 그럼 하위 부분은 한 단계 더 깊게 갈수 있는데, 여기선 취양이 좌지우지 할텐데 Name Price 라벨은 걍 큰 컨테이너에 붙였고, title 1개 컴포넌트 본문 row 1개 컴포넌트로 나눴다.
이게 완전 잘게 쪼갠거고 크게 퍼포먼스 부하 있을거 없고 재생산 할 것도 별로 없으면
title과 본문을 묶어 1개 컴포넌트로 봐도 무방하다.

2단계 React를 이용해 정적 버전 만들기

import React 해와서 만들어란 뜻임. state 등 데이터 고려 없이 걍 UI만

3단계: UI state에 대한 최소한의 (하지만 완전한) 표현 찾아내기

최소한의 state만 사용해라! 쓸데없는 state 만들지 말라 이말임
핵심 : DRY(Don't Repeat Yourself!)
즉 음식점에 어떤 기능의 컴포넌트를 만들때
state들을 state1 = 떡볶이, state2 = 파스타, 된장찌개.. 이러지 말고
let foodState = [떡볶이, 파스타, ..]이런식으로 변수 -> 배열 그렇게 써라는 뜻

4단계: State가 어디에 있어야할 지 찾기

대개는 차상위 컴포넌트에 state가 있으면 된다 몇년 전에 velopert 개발자가 설명해서 유명해진 프레젠테이셔널 컴포넌트와 컨테이너 컴포넌트로 나누고, 데이터 state 부분은 컨테이너 컴포넌트의 차상위 부분인 page 기능하는 js 파일에 두고 Top-Down 형식으로 사용했는데,
최근 프로젝트에서 내가 맘에 들어 사용하고 있는 구조는 Component 폴더랑 Page폴더랑 나눠서
page 폴더를 과거 컴포넌트 컨테이너 처럼 redux를 사용하거나 데이터를 받아서 하위 컴포넌트(Component폴더 내에 아토믹으로 설계된 view 기능만 하는 컴포넌트들)에 뿌려주는 구조를 즐겨 쓰고 있다.

5단계: 역방향 데이터 흐름 추가하기

이부분은 이해가 조금 안되는데, 역방향이면 보통은 handler 함수 만들어서 최상위 컴포넌트에서 props로 전달해서 하위 컴포넌트에서 그 함수를 받아서 거기에 setState(data) 이런식으로 data를 set 해주면 전체 상위에서 부터 새로운 데이터를 받고 업데이트된다. 즉 컴포넌트가 Container => LoginPage => Form => Input 으로 위계가 잡힌다 쳤을때, Input에서 타이핑 한 text data를 LoginPage에서 사용하고 싶으면 container에서 함수를 만들어서 input까지 Top-Down으로 함수를 내려주고, input 컴포넌트에서 그 함수를 onChange로 건다.
그러면 타이핑 한 데이터는 역방향, 즉 Container 컴포넌트의 우리가 건 함수로 넘어가고, 거기서 setState(데이터) 해주면 위에 전체 컴포넌트가 다 리랜더링 되면서, 데이터를 Container => LoginPage... 등 전달 가능해진다.
그래서 역방향 전송이 가능해진다.

사실 내가 생각하는데 React 사고방식은 UI그릴때 컴포넌트화 시킬수 있는거 그게 전부가 아닐까 생각한다.

출처 : https://reactjs-kr.firebaseapp.com/docs/thinking-in-react.html

담주에 Advance 읽어 봐야겠다

알고리즘 2문제

  1. 자릿수 합 구하기
    답안:
let str = [128, 460, 603, 40, 521, 137, 123];
console.log(solution(str));

// 다른 풀이
function solution(arr) {
  let answer,
    max = Number.MIN_SAFE_INTEGER;
  for (let x of arr) {
    let sum = 0,
      tmp = x;
    //while(true) 일때 계속 무한루프, false면 빠져 나감
    while (tmp) {
      //1의 자리 추출, 더하기
      sum += tmp % 10;
      //그후 루프 다시 탐
      //1의 자리 제거하고 10,100의 자리를 1의자리 10의자리로 만들어 버리기
      tmp = Math.floor(tmp / 10);
    }

    if (sum > max) {
      max = sum;
      answer = x;
    } else if (sum === max) {
      if (x > answer) answer = x;
    }
  }
  return answer;
}

난 숫자를 문자열 전환, for문 돌려서 숫자 낱개로 하나하나 더해서 비교하고 산출했는데
위 알고리즘은 3자리수에 첨에 10을 나눠주고, 나머지는 더해주고, 나눠준 값을
다시 10으로 나누어 자릿수 변경하고 floor 처리 해서 1의자리 제거 해주고 해서..
while() 값이 0까지 루프 돌게 한다음 더해주는 로직이다.
while(조건참이면 돈다){}
while문도 제법 유용한데 오랫동안 안쓰니 낯설게 느껴진다.

  1. K번째 큰 수
    현수는 1부터 100사이의 자연수가 적힌 N장의 카드를 가지고 있습니다. 같은 숫자의 카드가 여러장 있을 수 있습니다. 현수는 이 중 3장을 뽑아 각 카드에 적힌 수를 합한 값을 기록하려 고 합니다. 3장을 뽑을 수 있는 모든 경우를 기록합니다. 기록한 값 중 K번째로 큰 수를 출력 하는 프로그램을 작성하세요.
    만약 큰 수부터 만들어진 수가 25 25 23 23 22 20 19......이고 K값이 3이라면 K번째 큰 값 은 22입니다. 답안 :
function solution(numOfCard, numOfPick, card) {
  let answer = 0;
  let answerArray = [];

  //정렬 부터 해야
  card.sort((a, b) => b - a);

  for (let i = 0; i < numOfCard; i++) {
    for (let j = i + 1; j < numOfCard; j++) {
      for (let k = j + 1; k < numOfCard; k++) {
        answerArray.push(card[i] + card[j] + card[k]);
      }
    }
  }
  // console.log(answerArray);

  answer = answerArray[numOfPick];
  return answer;
}
let numOfCard = 10,
  numOfPick = 2;
let card = [13, 15, 34, 23, 45, 65, 33, 11, 26, 42];
console.log(solution(numOfCard, numOfPick, card));

뽑을 수 있는 모든 3개로 만든 수의 각각 합을 구한다. (같은 수 여러개 있을 수 있음)
그중 k번째 큰 수 출력.
3수를 선택하는데, 제일 큰수, 그다음 큰수, 그다음 큰수 픽 1, 그리고 다음은 ... 마지막에 그다음 큰수 옆의수를
픽 1 .. 다음은 옆의옆의 수를 픽1.. 하는 구조니

즉 세 수를 픽할때 마지막 픽한수가 1회전 돌면, 이제 두번째 픽한수가 한칸 옆으로 가고 또 1회전 돌고..
그럼 2번째 픽하는 수도 1회전 돌면서 윗 과정을 반복하고..
또 2번째 가 1회전 돌면 첫번째 픽한 수도 변경되면서 1회전 도니까
결국 세가지수가 각각의 for문으로 인덱스를 픽해줘야한다. 각각 다들 연달아 1회전씩 돌아야 하니까.
그래서 삼중 for문 만들고 그 합한 값은 1차원 배열에 넣어준 다음!
정해진 k번째 인덱스를 출력해주면 답이 나온다.

출력 : 143 (3번째 큰수가 143)

profile
낭만닥터와 슬의를 보고 저런 개발자가 되어야 겠다고 꿈꿔봅니다.

0개의 댓글