Etc/기록들

[TIL] 5월 3일 기록

NaDuck 2023. 5. 4. 10:21

오늘의 할 일

  •  📌 어제자 TIL - [내일 할 일] 확인
  •  📌 ~20:00 팀 데일리 미션 출제
  •  📌 ~다음날 06:00 팀 데일리 미션 답변
  •  📌 TIL 작성
  • [React로 데이터 다루기] 4-12 수강하기

 

오늘의 나는 무엇을 잘했을까?

  • 면스에서 열심히 대답했다.. 아는 질문이라 막힘없이 잘 말했고, 추가적으로 케니가 더 알면 좋은 점들을 말해줘서 한 번 더 리마인드할 수 있었다.
  • 오늘 페어 프로그래밍 전에 UI를 작성하는 일을 했다. 항상 벼락치기 인간이라 데드라인에 아슬아슬하게 했었는데, 팀플인만큼 조금씩이라 매일 할려고 노력중이고 계속 실천 중👍

 

오늘의 나는 무엇을 배웠을까? ⭐(중요체크)

React로 데이터 다루기

file input 초기화하기

프로그래밍에선 file input의 value를 빈 문자열''로만 설정할 수 있다. → 즉 프로그래밍에서 ''로 설정하면 초기화된다.

function FileInput({ name, value, onChange }) {
	const handleClearClick = () => {
    const inputNode = inputRef.current;  // 👈 input 태그가 렌더링됐는지 먼저 확인
    if (!inputNode) return;

    inputNode.value = '';  // 👈 value prop을 ''로 설정
    onChange(name, null); // 👈 state에선 null로 따로 설정
  };

	return (
    <div>
      <input type="file" onChange={handleChange} ref={inputRef} />
      {value && <button onClick={handleClearClick}>X</button>}
    </div>
  );
}

 

ref & useRef 정리

1. ref 객체 생성

import { useRef } from 'react';

// ...

const ref = useRef();

useRef() 호출하여 return되는 ref 객체를 변수에 저장

 

2. ref 지정하기

DOM 노드를 얻으려는 태그의 ref prop에 설정하기

<div ref={ref}> ... </div>

 

3. ref 객체에서 DOM 노드 참조하기 = ref.current

const node = ref.current;
if (!node) {
	// DOM 노드가 렌더링 X
}

 

ex) img 태그의 widht, height 구하기

import { useRef } from 'react';

function Image({ src }) {
  const imgRef = useRef();

  const handleSizeClick = () => {
    const imgNode = imgRef.current;
    if (!imgNode) return;

    const { width, height } = imgNode;
    console.log(`${width} x ${height}`);
  };

  return (
    <div>
      <img src={src} ref={imgRef} alt="크기를 구할 이미지" />
      <button onClick={handleSizeClick}>크기 구하기</button>
    </div>
  );
}

 

이미지 파일 미리보기 obejctURL

  • file 객체를 obejctURL로 만들면 file에 대한 주소를 만들어낼 수 있음
  • createObjectURL(file 객체): 해당 파일의 주소처럼 쓸 수 있는 문자열을 return(blob으로 시작하는 임시로 생성된 주소임)
  • 인터넷에 올린 파일같이 사용자 컴퓨터에 있는 파일을 주소로 사용할 수 있음 → 이미지 파일인 경우, 미리보기용 img 태그의 src 속성에 적용하면 됨
import { useEffect, useRef, useState } from 'react';

function FileInput({ name, value, onChange }) {
  const [preview, setPreview] = useState();
  const inputRef = useRef();

  // value가 바뀔 때마다 objectURL을 만들어냄 -> preview state에 저장
  useEffect(() => {
    if (!value) return;
    const nextPreview = URL.createObjectURL(value); // 👈 해당 파일의 주소처럼 쓸 수 있는 문자열 값 
    setPreview(nextPreview);
  }, [value]);

  return (
    <div>
      <img src={preview} alt="이미지 미리보기" /> // 👈 img의 src에 obejctURL을 넣어주면 파일 미리보기 가능
      <input type="file" accept="image/png, image/jpeg" onChange={handleChange} ref={inputRef} />
      {value && <button onClick={handleClearClick}>X</button>}
    </div>
  );
}

export default FileInput;

 

리액트 컴포넌트에서 외부의 상태를 변경할 때 useEffect를 활용한다

side effect란?

const nextPreview = URL.createObjectURL(value);

createObjectURL웹 브라우저의 메모리를 할당하여 임시 주소를 만드는데, 이런 식으로 컴포넌트에서 외부의 상태를 변화시키는 것을 side effect라고 한다.

그런데 계속해서 file input value가 바뀔 때마다 이 코드를 호출하기 때문에 계속해서 웹 브라우저의 메모리를 할당해주게 됨 → 다른 파일을 선택하거나 파일 선택을 해제했을 때 기존의 메모리 할당을 해제해주는 정리가 필요함

useEffect 함수는 side effect를 만들고 나서 정리하는 방법도 제공함: useEffect 함수의 콜백에서 return할 함수를 정하면 된다.

useEffect(() => {
    if (!value) return;
    const nextPreview = URL.createObjectURL(value);
    setPreview(nextPreview);

	// 정리 함수
    return () => {
      setPreview(); // state 값을 초기화하고
      URL.revokeObjectURL(nextPreview); // 메모리 할당 해제
    };
  }, [value]);
  • revokeObjectURL: 생성했던 objectURL의 메모리를 할당 해제한다.
  • 위 코드에서 value state가 바뀌면 렌더링 이후에 useEffect의 콜백 함수가 실행되는데, 그러면 이전에 만든 side effect가 더 이상 필요없기 때문에 리액트는 정리 함수(return문에서 설정한 함수)를 실행해서 side effect를 정리한다.

 

오늘의 나는 무엇이 궁금했나?

useRef에 대해 많이 헷갈렸는데, 계속 고민해보다가 해결됐다. 같이 고민해준 앤디랑 티나, 이안에게도 같이 공유 완료🤟

 

오늘 하루 회고

페어 프로그래밍을 하긴 이전에 대략적인 UI 구성을 하려고 저녁부터 팀원과 함께 했는데, 디자인이 어렵기도 하고 피그마에 익숙치 않아서 생각보다 시간이 많이 걸렸다. 이런 경우도 생각해서 데일리 미션 답변을 따로 시간을 빼서 했어야 했는데 그러지 못해서 완전히 늦게 끝나버렸다.. 이번을 통해서 일의 우선순위를 정해서, 좀 더 여유있게 수행하고, 좀 더 자세한 계획을 세워야겠다.