https://react.vlpt.us/basic/09-multiple-inputs.html
// 인풋 필드 여러개 다루기
import React, { useState } from 'react'
export default function PracticeInput() {
const [input, setInput] = useState({
name : '',
nickname : '',
});
const {name, nickname} = input;
const onChange = (e) => {
const {name, value} = e.target;
setInput({
...input,
[name]:value,
})
}
const onReset = () => {
setInput({
name : '',
nickname : ''
})
}
return (
<div>
<span>이름 : </span>
<input
type="text"
placeholder='이름'
name='name'
onChange={onChange}
value={name}
/>
<br/>
<span>닉네임 : </span>
<input
type="text"
placeholder='닉네임'
name='nickname'
onChange={onChange}
value={nickname}
/>
<br/>
<button onClick={onReset}>초기화</button>
</div>
)
}
불변성을 지켜주어야만 리액트 컴포넌트에서 상태가 업데이트가 됐음을 감지 할 수 있고
이에 따라 필요한 리렌더링이 진행된다.
또한 컴포넌트 업데이터 성능 최적화를 제대로 할수 있기도 하다.
리액트에서 객체를 업데이트하게 될 때에는 기존 객체를 직접 수정하면 안되며
새로운 객체를 만들어서 새 객체 변화를 주어야 한다.
useRef
특정 DOM을 선택해야할 때 사용
함수형 컴포넌트에서 ref 를 사용하여 useRef() 함수를 사용한다.
클래스형 컴포넌트에서는 콜백 함수를 사용하거나 React.createRef() 를 사용한다.
const nameInput = useRef('');
const onReset = () => {
setInput({
name : '',
nickname : ''
});
nameInput.current.focus();
}
<input
type="text"
placeholder='이름'
name='name'
onChange={onChange}
value={name}
ref={nameInput}
/>
useRef 로 컴포넌트 안의 변수 관리하기
useRef 로 관리하는 변수는 값이 바뀐다고 하여 컴포넌트가 리렌더링 되지 않는다.
리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고나서 그 다음 렌더링 이후 업데이트 된 상태를 조회할 수 있지만,
useRef 로 관리하고 있는 변수는 설정 후 바로 조회가 가능하다.
- scroll 위치
- 외부 라이브러리를 사용하여 생성된 인스턴스
- setTimeout, setInterval 을 통하여 만들어진 id
등의 값을 관리할 수 있다.
useRef 를 사용할 때 파라미터 값을 넣어주면 이 값이 current 값의 기본값이 된다.
그리고 이 값을 수정하려고 한다면 .current 로 조회하거나 수정하면 된다.
map 함수 사용하여 컴포넌트 그리기
export default function PracticeArray() {
const tmpArr = [
{
name : '강아지',
email : 'dksdksa',
},
{
name : '고양이',
email : 'sa',
},
{
name : '앵무새',
email : 'qqqwera',
}
]
return (
<div>
{tmpArr.map((e, idx)=> {
e['id'] = idx;
return <PracticeArrayItem {...e} />
})}
</div>
)
}
리액트에서의 배열 변화
배열에 변화를 줄 때에는 객체와 마찬가지로, 불변성을 지켜주어야 한다.
그렇기 때문에, 배열의 push, splice, sort 등의 함수를 사용하지 않아야한다.
만약에 사용해야 한다면, 기존의 배열을 한번 복사하고 나서 사용할 것
불변성을 지키면서 배열에 새 항목을 추가하는 방법에는
1. 전개 연산자 사용
export default function PracticeArray() {
const [inputs, setInputs] = useState({
username: '',
email: '',
})
const [users, setUsers] = useState([
{
id:0,
username : '강아지',
email : 'dksdksa',
},
{
id:1,
username : '고양이',
email : 'sa',
},
{
id:2,
username : '앵무새',
email : 'qqqwera',
}
]);
const nextId = useRef(3);
const onCreate = () => {
const newUser ={
id:nextId.current,
username : username,
email:email,
}
setUsers([
...users,
newUser,
])
setInputs({
username :'',
email:'',
})
nextId.current++;
}
const onChange = (e) => {
const {name, value} = e.target;
setInputs({
...inputs,
[name] : value,
})
}
const {username, email} = inputs;
return (
<div>
<CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate}/>
<UserList users={users} />
</div>
)
}
2. concat() 함수 사용
원래의 배열을 수정하지 않고 새로운 원소가 추가된 새로운 배열을 만들어준다.
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
삭제나 수정의 경우는 id 값을 활용할 것
const onDelete = (id) => {
setUsers(users.filter((e) => e.id !== id));
}
특정 id 를 인자로 받아서 filter 메서드를 사용하여 삭제를 구현
const onToggle = (id) => {
setUsers(users.map((user) =>
user.id === id
? {...user, active: !user.active}
: user
))
}
Mount 시 하는 작업
- props로 받은 값을 컴포넌트의 로컬 상태로 설정
- 외부 API 요청 (REST API)
- 라이브러리 사용
- setInterval 을 통한 반복작업이나 setTimeout 을 통한 작업 예약
Unmount 시 하는 작업
- setInterval, setTimeout 을 사용하여 등록한 작업들 clear 하기 - clearInterval, clearTimeout
- 라이브러리 인스턴스 제거
useEffect() 의 deps 에 특정 값 넣기
deps 에 특정 값을 넣게 된다면,
1. 컴포넌트가 처음 마운트 될 때에도 호출이 되고,
2. 지정한 값이 바뀔 때에도 호출되고,
3. 언마운트시에도 호출이되고,
4. 값이 바뀌기 직전에도 호출이 된다.
useEffect 안에서 사용하는 상태나 props 가 있다면 deps 에 넣어주는 것이 규칙
만약 넣지 않는다면 useEffect 에 등록한 함수가 실행 될 때 최신 props나 상태를 가리키지 않게 된다.
deps 파라미터를 생략하면
컴포넌트가 리렌더링 될 때마다 호출된다.
리액트 컴포넌트는 부모 컴포넌트가 리렌더링 되면 자식 컴포넌트의 변경 사항이 없다고 해도 리렌더링 된다.
이는 Virtual DOM 에 해당되며, 실제 DOM에는 바뀐 내용이 있는 컴포넌트만 변화가 반영되는 것이다.
이는 최적화가 가능하여 기존의 내용을 그대로 사용하면서 Virtual DOM에 렌더링 하는 리소스를 아낄 수 있다.
useMemo
성능 최적화를 위하여 연산된 값을 저장하는 Hook 이다.
useMemo(콜백함수, deps 배열)
배열에 담긴 내용이 바뀌면 등록된 콜백 함수를 호출하여 연산 후, return 으로 들어오는 값을 useMemo 로 지정해준 변수에 저장해준다.
즉, 관련없는 state 나 props가 변경될 때, useEffect 가 호출할 필요가 없는 경우, 이를 막기 위해 사용해주는 것임
useMemo는 특정 결과값을 재사용할 때 사용한다.
이와 유사한 훅으로는 useCallback 이 존재하며, 특정 함수를 새로 만들지 않고 재사용하고 싶을 때 사용해주는 훅이다.
기본적으로 컴포넌트가 리렌더링 될 때마다 선언해준 함수들도 재선언되므로 이를 방지하기 위해서
const onCreate = useCallback(() => {
const newUser ={
id:nextId.current,
username : username,
email:email,
}
setUsers([
...users,
newUser,
])
setInputs({
username :'',
email:'',
})
nextId.current++;
}, [users, username, email]);
const onDelete = useCallback((id) => {
setUsers(users.filter((e) => e.id !== id));
}, [users])
const onToggle = useCallback((id) => {
setUsers(users.map((user) =>
user.id === id
? {...user, active: !user.active}
: user
))
}, [users]);
함수의 선언부를 useCallback() 으로 감싸주면 된다.
다만 함수 안에서 사용하는 상태나 props 는 deps 배열 안에 포함시켜야한다.
'Web Study' 카테고리의 다른 글
리액트와 리덕스로 TodoList 만들기 (삭제, 완료, 추가) (0) | 2023.04.09 |
---|---|
리덕스 사용을 위한.. useReducer 개념 (0) | 2023.04.07 |
useContext ? (0) | 2023.04.04 |
React.memo()에 대해 (0) | 2023.04.03 |
게시판 서비스 시작 - DB 구축 (0) | 2023.03.16 |