컴포넌트의 porps가 바뀌지 않았다면, 리렌더링을 방지하여 컴포넌트의 리렌더링 성능 최적화를 해줄 수 있는 React.momo 함수
컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링을 하도록 설정해줄 수 있다.
사용법 : 감싸주기만 하면 된다!.
import React from 'react';
const CreateUser = ({ username, email, onChange, onCreate }) => {
return (
<div>
<input
name="username"
placeholder="계정명"
onChange={onChange}
value={username}
/>
<input
name="email"
placeholder="이메일"
onChange={onChange}
value={email}
/>
<button onClick={onCreate}>등록</button>
</div>
);
};
export default React.memo(CreateUser);
import React from 'react';
const User = React.memo(function User({ user, onRemove, onToggle }) {
return (
<div>
<b
style={{
cursor: 'pointer',
color: user.active ? 'green' : 'black'
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
});
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map(user => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default React.memo(UserList);
적용을 다 하고나서, Input을 수정할 때 하나라도 수정하면 모든 User들이 리렌더링되고, CreateUser도 리렌더링이 된다.
users배열이 바뀔때마다 onCreate도 새로 만들어지고, onToggle, onRemove도 새로 만들어지기 때문이다.
deps에 users가 들어있기 때문에 배열이 바뀔때마다 함수가 새로 만들어지는건 당연하다.
바로 deps에서 users를 지우고, 함수들에서 현재 useState로 관리하는 users를 참조하지 않게 하는것이다.
정답은 바로, 함수형 업데이트
함수형 업데이트를 하게 되면, setUsers에 등록하는 콜백함수의 파라미터에서 최신 users를 참조할 수 있기 때문에 deps에 users를 넣지 않아도 된다.
=> 이렇게 해주면, 특정 항목을 수정하게 될 때, 해당 항목만 리렌더링 될 거다.
export default React.memo(
UserList,
(prevProps, nextProps) => prevProps.users === nextProps.users
);
하지만, 이걸 잘못사용한다면 오히려 의도치 않은 버그들이 발생하기 쉽다.
ex) 함수형 업데이트로 전환을 안했는데 이렇게 users만 비교를 하게 된다면, onToggle과 onRemove에서 최신 users배열을 참조하지 않으므로 심각한 오류가 발생할 수 있다.
function reducer(state, action) {
// 새로운 상태를 만드는 로직
// const nextState = ...
return nextState;
}
액션의 예시 .
// 카운터에 1을 더하는 액션
{
type: 'INCREMENT'
}
// 카운터에 1을 빼는 액션
{
type: 'DECREMENT'
}
// input 값을 바꾸는 액션
{
type: 'CHANGE_INPUT',
key: 'email',
value: 'tester@react.com'
}
// 새 할 일을 등록하는 액션
{
type: 'ADD_TODO',
todo: {
id: 1,
text: 'useReducer 배우기',
done: false,
}
}
이처럼 action 객체의 형태는 자유다.
type 값을 대문자와 _로 구성하는 관습이 존재하기도 하지만, 꼭 따라야 할 필요는 없다.
const [state, dispatch] =
useReducer(reducer, initialState);
예를 들어서 컴포넌트에서 관리하는 값이 딱 하나고, 그 값이 단순한 숫자, 문자열 또는 boolean 값이라면 확실히 useState 로 관리하는게 편할 것입니다.
const [value, setValue] = useState(true);
하지만, 만약에 컴포넌트에서 관리하는 값이 여러개가 되어서 상태의 구조가 복잡해진다면 useReducer로 관리하는 것이 편해질 수도 있습니다.
const [<상태 객체>, <dispatch 함수>] = useReducer(<reducer 함수>, <초기 상태>, <초기 함수>)
=> 벨로퍼트님 같은 경우네는 setter를 한 함수에서 여러번 사용해야 하는 일이 발생한다면, 이때부터 useReducer를 쓸까 고민을 한다고 한다.
setUsers(users=> users.concat(user));
setInputs({
username: '',
email:''
});
input의 키값 [name]
input[name] = value 로 키 값을 교체해준다고 이해하면 된다.
name,
value, 의 표현과 같다.
좋은 글 감사합니다! >_o