JUSTCODE - Week3(Hooks, useState, useRef, props, useEffect)

김정현·2022년 10월 18일

JUSTCODE

목록 보기
7/20
post-thumbnail

리액트 공식 문서: https://ko.reactjs.org/docs/hooks-intro.html

Hooks

Hook:
함수 컴포넌트에서 React state와 생명주기(lifecycle) 기능을
연동(hook into) 할 수 있게 해주는 함수
Hook은 클로저 개념을 활용하여 구현된 기능이다
react모듈로부터 { Hook명 }을 import하여 사용한다

Hook의 규칙

  1. 함수 컴포넌트의 최상위에서만 Hook을 호출해야 한다
  2. 반복문, 조건문, 중첩문 함수 내에서는 Hook을 실행하지 않는다(1번과 같은 내용)
  3. React 함수 컴포넌트 내에서만 Hook을 호출해야 한다

useState

State

useState Hook을 통해 정의한다
컴포넌트 내부에서 가지고 있는 컴포넌트의 상태값을 의미한다
클로저의 함수가 호출된 후에도 변수가 살아있는다는 특징을 활용하여 동작한다

state는 js에서 변수의 역할과 같다
변수가 아닌 state를 사용하는 이유는, state는 새로고침 없이
이벤트를 통한 값의 변화가 생길 때 마다 상태값을 갱신할 수 있기 때문이다

import React, { useState } from "react";

function App() {
  const [state, setState] = useState("초기값"); 
  // state는 값, setState는 setter함수이다
  // ⚠️ map을 사용하기 위한 state의 경우 초기값을 반듯이 배열로 설정해야 한다
  
  return (
    <>
  	 {state}
     <tag on+event={() => {newState("갱신값");}}></tag>
     {state} //이벤트 발생시 state의 값이 갱신값으로 변경됨
  	</>
  );
}

export default App;
객체값을 가진 state에서 일부 프로퍼티만 갱신하는 방법

setState(prev => ({ ...prev, [변경할 프로퍼티명]: 변경할 값 })
//여기서 prev는 변경 전의 값을 가지고 있다
//따라서 전개연산자로 객체를 해제한 뒤, 추가/변경할 값을 넣어주는 것

useRef

JS에서 특정 DOM을 선택하기 위하여,
getElementBy-, querySelector과 같은 DOM Selector을 사용하듯이
리액트에서 DOM을 직접 선택해야 할 때, ref를 사용한다
실시간으로, 태그의 값을 받아와야 할 때 사용한다

import {useRef} from 'react';

const 변수명1 = useRef(); // ref를 변수명에 할당

function() {
	console.log(변수명1.current.value); // current를 붙여야 현재 값을 받아올 수 있다
}

return (
	<태그 ref={ 변수명1 }></태그> 
    // ref를 통해 해당 태그를 선택, 
    // 선택 이후 상단 부분에서 태그와 태그의 값을 조작할 수 있다
)

⚠️ 실시간으로 받아와야 하는 값은 state가 아닌 ref를 사용해서 불러온다

Props

properties의 약자로, 컴포넌트의 속성값을 의미하며
부모 컴포넌트로 전달 받은 데이터를 지니고 있는 객체이다
props를 통해, 부모 컴포넌트에서 자식 컴포넌트로 모든 JS값과 컴포넌트를 상속할 수 있다
자손 노드로 정보를 전달하고 싶은 경우, 연결된 자식을 따라 props를 전달해줘야 한다
부모 노드에서 자식 노드로 단방향 바인딩을 가진다

React의 트리 구조

React는 최상위 노드인 루트 노드를 시작으로
router, routs, 컴포넌트로 이어지는 구조를 가진다
연결된 노드들은 부모 노드, 자식 노드, 조상 노드, 자손 노드 등의 관계를 가진다
레벨과 같은 계층 구조를 가진다
props상속 시 key속성이 없다면 에러가 발생한다

props 전달 방법

//Parent.js(부모 컴포넌트)

import Child from '자식 컴포넌트 경로';
function Parent() {
	return (
    	<Child 속성명1={전달할 값1} 속성명2={전달할 값2}>
    )
}

export default Parent;
//Child.js(자식 컴포넌트)

function Child(props) {
	return (
    	<태그 props.속성명1></태그> // props를 통해 객체, 함수, 컴포넌트 등 
        <태그 props.속성명2></태그> // 다양한 값을 전달하여 사용할 수 있다
    )
}

export default Child;
//props객체를 구조분해 할당하여 전달할 수 있다

function Child({속성명1, 속성명2}) {
	return (
    	<태그 속성명1></태그>
        <태그 속성명2></태그>
    )
}

useEffect

원하는 타이밍(의존성 배열)에 부수 효과를 일으키기 위하여 사용한다
데이터 fetch, 이벤트 관리등에 사용한다

useEffect는 랜더링(JSX return) 후에 콜백 함수를 실행시킨다
부수 효과를 일으키는 시기는, useEffect의 두 번째 인자인 의존성 배열을 통해 설정할 수 있다
useEffect는 초기 랜더링에서 한 번 실행되며, 이후로는 조건에 해당되는 경우만 실행된다

⚠️ 이벤트 콜백으로 useState의 setter를 실행하여 state의 값을 업데이트 할 때는, 
⚠️ 이벤트 콜백 안에서 어떤 방법으로도 업데이트 된 값에 접근할 수 없기 때문에 
⚠️ useEffect의 의존성 배열에 업데이트한 값을 넣은 뒤,
⚠️ 이어서 실행하고 싶은 동작을 useEffect의 콜백으로 실행시킨다

⚠️ useEffect안에서는 setter로 state값을 변경하기 전부터
⚠️ 변경값이 출력되는데 useEffect와 setter의 동작 순서를 알아볼 필요가 있을 것 같다
useEffect (실행시킬 동작, [의존성 배열])

//의존성 배열이 없다면 모든 랜더링에서 실행된다
//의존성 배열이 비어있다면 초기 랜더링에서만 실행된다
//의존성 배열의 요소가 있다면 요소에 변화가 생기는 랜더링에서 실행된다
//의존성 배열의 요소는 최소화하는 것이 좋다

Cleanup Effect

이전에 일으킨 부수 효과를 정리할 때 사용한다

렌더링(rendering)

react에서 함수 컴포넌트의 렌더링이란,
tate, props를 기반으로 요소를 그려내는 행위이다

함수 컴포넌트의 렌더링 순서
1. 컴포넌트 렌더링(mount)
2. 최초 렌더링에서 useEffect 첫 번째 인자로 넘겨준 콜백 실행(side effect)
3. state, props에 변화가 생기는 경우 리렌더링 발생
4. 의존성 배열 체크에 따라 추가 리렌더링
5. unmount

render, clean up, Effect 실행 순서

이미지 출처: https://github.com/donavon/hook-flow

부수 효과(side effect)

랜더링 외적인 영역에 영향을 주는 어떠한 행위
의도되지 않은 부수 효과는 랜더링 성능을 저하시킨다

생명주기(life cycle)


KodeKata

22.10.19

const getLengthOfStr = str => {
  temp = "";
  max = 0;

  for(let i = 0; i < str.length; i++){
    if(!temp.includes(str[i])){
      temp += str[i]
    } else {
      if(temp.length > max) max = temp.length;
      temp = str[i]
    }
  }
  return Math.max(max, temp.length);
}

console.log(getLengthOfStr("abcweabcabc"));
console.log(getLengthOfStr("aaaaba"));
console.log(getLengthOfStr("sttrgaqe"));

22.10.20

const sameReverse = num => {
  num = String(num)
  let changeNum = ""

  for(let i = num.length-1; i >= 0; i--){
    changeNum += num[i];
  }
  
  let answer = num === changeNum ? true : false
  return answer
}

console.log(sameReverse(123))
console.log(sameReverse(1221))
console.log(sameReverse(-121))
console.log(sameReverse(10))

22.10.21

const getPrefix = (strs) => {
  let arr = new Array(strs[0].length);
  let answer = "";

  for (let i = 0; i < strs.length; i++) {
    for (let j = 0; j < strs[i].length; j++) {
      if (i === 0) {
        arr[j] = strs[i][j];
      } else {
        if (arr[j] !== strs[i][j]) {
          arr[j] = null;
        }
      }
    }
  }

  let count = 0;
  while (arr[count] !== null) {
    answer += arr[count];
    count++;
  }

  return answer;
};

console.log(getPrefix(["start", "stair", "step"]));
console.log(getPrefix(["start", "wework", "today"]));
profile
개발 공부 블로그

0개의 댓글