useRef
React를 사용하는 프로젝트에서도 DOM에 직접 접근해야 하는 아래와 같은 경우가 있을 수있다. 아래와 같은 경우에 React에서는 ref를 사용한다.
- 특정 엘리먼트의 크기와 스크롤바 위치를 설정시
- 포커스 설정시
- 외부라이브러리를 특정 DOM에 적용해야 할 때
useRef()를 사용하여 Ref 객체를 만들고, 이 객체를 우리가 선택하고 싶은 DOM에 ref 값으로 설정해주어야 한다. 그러면, Ref 객체의 .current값은 우리가 원하는 DOM을 가르키게 된다.
import React, { useState, useRef } from 'react';
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: ''
});
const nameInput = useRef();
const { name, nickname } = inputs; // 비구조화 할당을 통해 값 추출
const onChange = e => {
const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
setInputs({
...inputs, // 기존의 input 객체를 복사한 뒤
[name]: value // name 키를 가진 값을 value 로 설정
});
};
const onReset = () => {
setInputs({
name: '',
nickname: ''
});
nameInput.current.focus();
};
배열 렌더링
배열이 고정적이라면 상관 없지만, 배열의 인덱스를 하나하나 조회하며 렌더링 하는 방법은 동적인 배열을 렌더링 하지 못한다.
동적인 배열을 렌저링해야 할 때에는 자바스크립트 배열의 내장함수 map()를 사용한다. map()는 배열안에 있는 각 원소를 반환하여 새로운 배열로 만든다. 리액트에서 동적인 배열을 렌더링해야 할 때는 해당 함수를 통해서 리액트 엘리먼트로 이루어진 배열로 변환해주면 된다.
// map 추가전
return (
<div>
<User user={users[0]} />
<User user={users[1]} />
<User user={users[2]} />
</div>
);
}
// map 추가후
return (
<div>
{users.map(user => (
<User user={user} />
))}
</div>
);
}
리액트에서 배열을 렌더링 할 때에는 key라는 props를 설정해야 한다. key 값은 각 원소들마다 가지고 있는 고유값으로 설정해야 한다. 만약 배열 안의 원소가 가지고 있는 고유한 값이 없다면 map() 함수를 사용 할 때 설정하는 콜백함수의 두번째 파라미터 index를 key로 사용하면된다.
만약 배열 렌더링링 시 key 설정을 하지 않았다면, 기본적으로 배열의 index를 키로 사용하게 되는데 이 경우 각 고유 원소에 key를 설정하는 것보다 비효율적이다.
key를 설정하지 않은 배열은 렌더링 시에 배열에 새로운 값이 추가되면, 추가된 값이 아닌 배열 전체를 다시 렌더링하는 반해, 고유값이 있는 경우기존의 값은 그대로 두고 새로운 값만 렌더링 한다.
useRef를 통한 컴포넌트 내부 변수 선언
useRef로 관리하는 변수는 값이 바뀐다고 해서 컴포넌트가 다시 렌더링 되지 않는다. 리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고 나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회 할 수 있는 반면, useRef로 관리하는 변수는 설정 후 바로 조회 할 수 있다.
const nextId = useRef(4);
const onCreate = () => {
// 나중에 구현 할 배열에 항목 추가하는 로직
// ...
nextId.current += 1;
};
return <UserList users={users} />;
}
export default App;
useRef()를 사용 할 때 파라미터를 넣어주면, 이 값이 .current 값의 기본값이 됩니다. 그리고 이 값을 수정 할때에는 .current값을 수정하면 되고 조회 할 때에는 .current를 조회하면 된다.
배열에 항목 추가
배열은 불변성을 지켜주어야 한다. 그렇기 때문에, 배열의 함수를 사용하면 안되고 기존의 배열을 한번 복사하고 나서 사용해야 한다. 배열에 새 항못을 추가 할 때에는 spread연산자를 사용하거나, concat을 사용하면된다.
const nextId = useRef(4);
const onCreate = () => {
const user = {
id : nextId.current,
username,
email
}
// 새로운 사용자 추가
setUsers(users.concat(user));
// 입력 필드 초기화
setInputs({
username : '',
email : ''
})
nextId.current += 1;
};
배열에 항목 제거
배열에 있는 항목을 제거할 때에는, 추가 할 때와 마찬가지로 불변성을 지켜가면서 업데이트를 해주어야 한다.
불변성을 지키면서 특정 원소를 배열에서 제거하기 위해서는 filter배열 내장 함수를 사용하는 것이 가장 편하다. 이 함수는 배열에서 특정 조건이 만족하는 원소들만 추출하여 새로운 배열을 만들어 준다.
const onRemove = id => {
// user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
// = user.id 가 id 인 것을 제거함
setUsers(users.filter(user => user.id !== id));
};
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} />
</>
);
배열에 항목 수정
배열의 불변성을 유지하면서 배열을 업데이트 할 때에도 map 함수를 사용할 수 있다.
id 값을 비교 id가 다른경우 그대로 두고, 같다면 active값을 반전 시키도록 구현할 수있다.
// onToggle 함수 구현 내용
const onToggle = id => {
setUsers(
users.map(user =>
// id가 다르다면 active값을 바꿔 색을 반전 시킨다.
user.id === id ? { ...user, active: !user.active } : user
)
);
};
// UserList.js
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
- 해당 코드 내용을 봤을때, id를 바꾸는 내용은 없는데 어떻게 id가 바뀐걸 기준으로 컬러를 바꾸는지 모르겠다.
'WINK-(Web & App) > React.js 스터디' 카테고리의 다른 글
[2025 겨울방학 React.js 스터디] 박현빈 # 1주차 (0) | 2025.01.18 |
---|---|
[2025 겨울방학 React.js 스터디] 백채린 #1주차 (0) | 2025.01.12 |
[2024-2 React.js 스터디] 이서영 #5주차 (0) | 2024.11.28 |
[2024-2 React.js 스터디] 윤아영 #5주차 (0) | 2024.11.27 |
[2024-2 React.js 스터디] 김지수 #6주차 (2) | 2024.11.27 |