되게 오랜만이라.... 그래서 다 까먹어버림 ㅋㅋ
전에 했던거 슥 보고 시작!
🔍 useRef 로 특정 DOM 선택하기
리액트에서도 DOM을 직접 선택해야 하는 상황이 있다 !!
ex) 1. 특정 엘리먼트의 크기를 가져와야 할 때
2. 포커스를 설정 해줘야 할 때
3. 외부 라이브러리를 사용해야 할 때 등등
ref - useRef
useRef: Hook 함수
getElementById, querySelector 같은 Selector 함수를 사용하는 자바스크립트와는 다르게
리엑트에서는 ref라는 걸 사용합니다. (함수형 컴포넌트에서 사용)
저번에 작성했던 InputSample 코드에 useRef를 추가했어요
추가된건 다음 3줄인데요
useRef()를 사용해 Ref 객체 nameInput을 생성함
생성한 객체를 현재 DOM에 focus() 메서드 호출/ 해당 요소에 포커스를 줌
해당 DOM요소에 nameInput이라는 ref를 연결(nameInput.current가 이 코드가 있는 요소를 가리킴)
🔍 배열 렌더링하기
이번 배열을 렌더링 하는 방법을 배워볼게요
- 그냥 그대로 코드 작성하기
왼쪽 처럼 그냥 주어진 배열을 그대로 작성해도 되지만 재사용되는 코드를 줄여서 오른쪽처럼 만들 수 있습니다 !!
왼쪽 코드의 단점
- 확장성 부족: user가 100명이면 100줄을 써야 함.
- 재사용 불가: user를 별도로 컴포넌트화 하지 않아 다른 곳에서 재활용 불가
❓왜 컴포넌트화 할 때 id는 안넘기나
A: id가 컴포넌트에서 직접적으로 사용되지 않기 때문에
-화면에 보여주는 것은 usernamerhk email뿐이므로 굳이 전달할 필요가 없다.
🧠 필요한경우
- 리스트를 렌더링할 때 key로 사용하기 위해
return (
<div>
{users.map(user => (
<User key={user.id} user={user} />
))}
</div>
);
여기서는 식별할 때 key로 사용
2. 내부 특정 동작에서 id가 필요할 때
function User({ user, onRemove }) {
return (
<div>
<b>{user.username}</b> <span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
이 경우에는 id도 간접적으로 사용되므로 id도 넘겨주어야 한다!!
다시 돌아와서 위에서 했던 방법들은 동적인 배열을 렌더링 하지 못함
그래서 !! 동적인 배열을 렌더링해야 할 때는 자바스크립트 배열의 내장함수 map()을 사용
map() 함수
배열안에 있는 각 원소를 변환하여 새로운 배열을 만들어줌
리액트에서 동적인 배열을 렌더링해야 할 때 일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열로 변환
아까 왜 id는 안하는지 찾아봤었는데 react에서 배열을 렌더링 할 때에는 key 라는 props를 설정해야 한대요
-key 값은 각 원소들마다 가지고 있는 고유값으로 설정을 해야함(지금의 경우엔 id가 고유 값)
❓ 그럼 그냥 무조건 id도 넘겨야 했던거 아닌가????
근데 이 코드를 보면 여전히 User컴포넌트를 만들 때 id를 넘기는게 아니라 map()에서 직접 설정 하고 있다..
✅ 왜 key를 User컴포넌트에 넘기지 않고, map() 에서 직접 쓰는가?
- Key는 React 내부에서만 사용됨
- key는 컴포넌트의 props가 아님
- React가 리스트 항목을 구분해서 효율적으로 리렌더링하기 위해 내부적으로 쓰는 값이에요
- 그래서 User 컴포넌트에서는 props.key로 접근할 수 없습니다
- Key는 컴포넌트 외부에서 설정해야 함
{users.map((user) => (
<User key={user.id} user={user} />
))}
이렇게 해야 react가 각 컴포넌트의 위치를 식별/성능 최적화를 할 수 있음
배열 안의 원소가 가지고 있는 고유한 값이 없다면 map() 함수를 사용 할 때 설정하는 콜백함수의 두번째 파라미터 index 를 key 로 사용
<div>
{users.map((user, index) => (
<User user={user} key={index} />
))}
</div>
💡 key의 존재유무에 따른 업데이트 방식
const array = ['a', 'b', 'c', 'd'];
array.map(item => <div>{item}</div>); //key값 없이
[
{
id: 0,
text: 'a'
},
{
id: 1,
text: 'b'
},
{
id: 2,
text: 'c'
},
{
id: 3,
text: 'd'
}
];
array.map(item => <div key={item.id}>{item.text}</div>); //key값 사용
- key값이 없으면 삽입/삭제시에 하나하나 원소를 바꾸는 방식으로 진행되서 비효율적
- key값이 있으면 그런 과정 없이 바로 바로 삽입/삭제 => 효율적
🔍 useRef 로 컴포넌트 안의 변수 만들기
useRef의 용도
1. DOM을 선택하는 용도 (위에서 다룸)
2. 컴포넌트 안에서 조회 및 수정 할 수 있는 변수 관리
- 값이 바뀌어도 컴포넌트 리렌더링 x
- 설정 후 바로 조회 가능
-다음과 같은 값을 관리 할 수 있음
- setTimeout, setInterval 을 통해서 만들어진 id
- 외부 라이브러리를 사용하여 생성된 인스턴스
- scroll 위치
useRef로 변수를 관리하기 전에 배열을 APP.js에서 선언하고 UserList에게 props로 전달을 해주는 방식으로 바꿔줬습니다
- useRef()에 들어가는 파라미터 = .current 값의 기본값
- 예제에서는 이미 id가 3까지 만들어져 있어서 4로 설정
- 수정할 때는 .current 값을 수정 조회할 때도 .current 조회
🔍 배열에 항목 추가하기
💡 배열에 변화를 줄 때
- 객체와 마찬가지로 불변성을 지켜야함 !
- 배열의 push, splice, sort 등의 함수 사용 x
- 사용 하려면 기존 배열 복사하고 나서 사용
새 항목을 추가하는 방법
1.spread 연산자 사용
- input 요소에서 값이 바뀌면 바뀐 부분 업데이트
- ...input으로 기존 상태 복사/유지 후 변경된 값만 덮어씌움
- setUsers로 새로운 사용자 추가 가능
- 새로운 생성되는 사용자는 id = 4로 설정 이후 1씩 증가
- username과 email을 받아서 새로운 사용자 객체 생성후 배열 업데이트
- 입력값 초기화
2.concat 함수 사용
concat 함수
- JavaScript 배열의 기존 배열을 변경하지 않고, 새로운 요소를 추가한 새로운 배열을 반환하는 메서드
- spread (...) 연산자와 기능은 비슷하지만 문법이 다름
- 원본배열.concat(새로 추가할 요소 or 배열)
🔍 배열 항목 제거하기
- 배열을 추가 하는 것과 마찬가지로 제거하는 것도 배열에 변화를 주는 것!
- => 불변성을 지켜야함. (filter 배열 내장 함수를 사용하는 것이 가장 편리)
filter() 함수
- JavaScript 배열 메서드
- 배열에서 특정 조건을 만족하는 요소들만 골라 새로운 배열을 만들 때 사용
- onRemove를 만들어서 파라미터로 주어진 id와 다른 값을 가진 user들만 모은 새 배열을만듬
=> 불변성을 지킴, 해당 id를 가진 user 삭제
이런식으로 삭제 버튼을 누르면 삭제가 되는 것을 확인 할 수 있습니다!!
🔍 배열 항목 수정하기
항목을 수정하는것도.... 배열에 변화를 주는 것이기 때문에!
불변성을 유지해 줘야겠죠??
예제는 유저명을 누르면 초록색 글씨로 on/off 하는 것....
- User를 만들때 onToggle까지 전달
- active가 true면 초록색으로 바꿈
- 클릭되면 onToggle을 이용해서 해당 id에 해당되는 유저명의 active값을 바꿔줌
❓  
하다가 이게 코드에 있길래 궁금해서 찾아봤습니다!!
: non-breaking space
: 일반 공백( )과 달리, 줄바꿈이 생겨도 이 공백에서는 줄이 안 바뀜
📦 언제 사용하나?
- 텍스트 사이를 강제로 띄우고 싶을 때
- 줄바꿈 없이 항상 붙어있게 하고 싶을 때
- 여러 개 연속 띄어쓰기를 표현하고 싶을 때 (HTML에선 보통 띄어쓰기 여러 개가 1개처럼 보임)
- 예제 코드에서는 그냥 한 칸 띄우려고 사용
🔍 useEffect를 사용하여 마운트/언마운트/업데이트시 할 작업 설정하기
useEffect
- Hook중 하나
- 컴포넌트가 렌더링된 이후에 어떤 “부수 효과(side effect)“를 수행하고 싶을 때 사용
- ex)
- 데이터를 가져오기 (fetch)
- 타이머 설정
- 이벤트 리스너 등록
- 로컬스토리지 접근 등
💡 기본문법
import { useEffect } from "react";
useEffect(() => {
// 여기에 부수 효과 코드를 작성
console.log("컴포넌트가 렌더링되었어요!");
// 클린업 함수 (선택적)
return () => {
console.log("컴포넌트가 언마운트되거나, 다시 실행되기 전 정리됩니다.");
};
}, [/* 의존성 배열 */]);
- 첫 번째 파라미터에는 함수
- 두 번째 파라미터에는 의존값이 들어있는 배열
주로 마운트 시에 하는 작업들
- props로 받은 값을 컴포넌트의 로컬 상태로 설정
- 외부 API요청
- 라이브러리 사용
- setInterval을 통한 반복작업 혹은 setTimeout을 통한 작업 예약
주로 언마운트 시에 하는 작업들
- setInterval, setTimeout 을 사용하여 등록한 작업들 clear 하기 (clearInterval, clearTimeout)
- 라이브러리 인스턴스 제거
👀 마운트 / 언마운트
- 의존성 배열이 빈 배열 => 처음 마운트될 때 한 번만 실행
- return () => {} 함수는 언마운트 될 때 실행
👀 deps에 특정 값 넣기
: 컴포넌트가 처음 마운트 될 때/ 지정한 값이 바뀔 때 호출
: deps안에 특정 값이 있다면 언마운트시/ 값이 바뀌기 직전에 호출
: useEffect 안에서 사용하는 상태 / props가 있다 >> useEffect의 deps에 넣어주어야 함
만약 넣지 않으면 useEffect에 등록한 함수가 실행 될 때 최신 props / 상태를 가르키지 않게 됨
👀 deps 파라미터를 생략하기
: 컴포넌트가 리렌더링 될 때마다 호출
++ 기본적으로 부모 컴포넌트가 리렌더링 되면 자식 컴포넌트도 리렌더링됨.
휴... 오랜만에 하니까 좀 힘들고.... 어렵고..... 다시 화이팅 ㅠ
'WINK-(Web & App) > React.js 스터디' 카테고리의 다른 글
[2025 1학기 React.js 스터디] 이승준 #4주차 (0) | 2025.05.07 |
---|---|
[2025 1학기 React.js 스터디] 이서준 #4주차 (1) | 2025.05.06 |
[2025 1학기 React.js 스터디] 이가인 #3주차 (0) | 2025.04.10 |
[2025 1학기 React.js 스터디] 이종민 #3주차 (0) | 2025.04.10 |
[2025 1학기 React.js 스터디] 최은희 #3주차 (0) | 2025.04.10 |