- React.memo2022년 05월 25일 10시 47분 30초에 업로드 된 글입니다.작성자: 원2728x90반응형
React.memo 는 컴포넌트의 props 가 변하지 않았으면 리렌더링을 방지해서 컴포넌트의 리렌더링 성능 최적화를 해줄 수 있음
컴포넌트에서 리렌더링이 필요한 상황에서만 리렌더링을 하도록 설정 할 수 있음
CreateUser.js
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);
function > const 로 변경후 감싸주면 됨
export default 에 CreateUser 를 React.memo 로 감싸주기만 하면 됨
UserList.js 도 해주자
import React, {useEffect} from "react"; const User = React.memo(function User({user, onRemove, onToggle}) { useEffect(() => { console.log(user); }); 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> ); }); // 순서상 UserList 에서 on Toggle 을 받아오고, User 에서 호출 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);
마찬가지로 function > const 변경후 감싸주기
react 개발자 도구를 보면 Memo 가 되어있다고 친절히 알려준다.... 그리고 해당 input 값에 값을 변경시켜보면 UserList 들이 리렌더링이 되지 않는것을 확인 할 수 있음
그런데 User 중 하나라도 수정(클릭을 해서 false 를 ture 로 변경 한다던지..) 하면 모든 User 이 리렌더링 되고 CreateUser 도 리렌더링이 됨.
>> 이유 users 배열이 변경 될 때 마다 해당 props 를 포함하고 있는 함수들 onCreate, onToggle, onRemove 도 영향을 받아서 새로 만들어지기 때문 > deps 에 users 가 들어있기 때문
이걸 최적화 하려면 deps 에서 users 를 지우고 함수들에서 현재 useState 로 관리하는 users 를 참조하지 않게 해야함
>> 함수형 업데이트를 사용해서 setUsers 에 등록하는 콜백함수의 파라미터에서 최신 users 를 참조 할 수 있음
>> deps에 users 를 넣지 않아도 됌
App.js
onChange, onCreate, onToggle, onRemove 를 수정해보자 (onChange 는 users가 없어서 영향이 없지만 연습ㄱ)
import React, {useCallback, useMemo, useRef, useState} from 'react'; import CreateUser from './components/CreateUser'; import UserList from "./components/UserList"; function countActiveUsers(users) { console.log("active 값이 ture 인 유저의 수를 센는중..."); return users.filter(user => user.active).length; } function App() { const [inputs, setInputs] = useState({ username: '', email: '' }); const {username, email} = inputs; const onChange = useCallback( e => { const {name, value} = e.target; setInputs(inputs => ({ // spread ...inputs, [name]: value })); }, []); // useState 를 사용하여 컴포넌트의 상태로 관리 const [users, setUsers] = useState([ { id: 1, username: 'velopert', email: 'public.velopert@gmail.com', active: true }, { id: 2, username: 'tester', email: 'tester@example.com', active: false }, { id: 3, username: 'liz', email: 'liz@example.com', active: false } ]); const nextId = useRef(4); const onCreate = useCallback(() => { const user = { id: nextId.current, username, email }; // concat 함수 setUsers(users => users.concat(user)); // spread 함수 // setUsers([ // //spread 문법 // ...users,user // ]); setInputs({ username: '', email: '' }); nextId.current += 1; }, [username, email]); const onRemove = useCallback( id => { // user.id 가 파라미터로 일치하지 않는 우너소만 추출해서 새로운 배열을 만듬 // = user.id 가 id 인 것을 제거함 setUsers(users => users.filter(user => user.id !== id)); }, []); const onToggle = useCallback( id => { setUsers(users => users.map(user => user.id === id ? {...user, active: !user.active} : user ) ); }, []); const count = useMemo(() => countActiveUsers(users), [users]); return ( <> <CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate} /> <UserList users={users} onRemove={onRemove} onToggle={onToggle}/> <div>활성 사용자 수 : {count}</div> </> ); } export default App;
이렇게 하면 해당 항목만 리렌더링이 됌 굳ㅋ 최적화 끝
리액트 개발을 할 땐 useCallback, useMemo, React.Memo 는 컴포넌트의 성능을 실제로 개선할수 있는 상황에서만 사용하자
User 컴포넌트에 <b> 와 button 에 onClick 으로 설정해준 함수들은 useCallback 으로 재사용한다해서 리렌더링을 막을 수 있는 것이 아니라 할필요없음
또한 렌더링 최적화를 하지 않을 컴포넌트에 React.memo 를 사용하는 것은 불필요한 props 비교만 하는 것이라 실제 렌더링을 방지 할 경우에만 사용하자
++
React.memo 에서 두번째 파라미터에 propsAreEqual 함수를 사용하여 특정 값들만 비교를 하는것도 가능
export default React.memo( UserList, (prevProps, nextProps) => prevProps.users === nextProps.users );
근데 이거 잘못쓰면 버그 많이 생김
함수형 업데이트로 전환을 안했는데 이렇게 users 만 비교하면 onToggle, onRemove 에서 최선 users 배열을 참조하지 않아서 오류 발생가능성이 있다.
728x90반응형'JS Library > React' 카테고리의 다른 글
Immer 라이브러리 (0) 2022.05.26 Context API 전역 값 관리 (0) 2022.05.26 커스텀 Hooks (0) 2022.05.25 useCallback 를 사용하여 함수 재사용 (0) 2022.05.25 React Developer Tools (0) 2022.05.24 useMemo 를 사용하여 연산한 값 재사용하기 (0) 2022.05.24 다음글이 없습니다.이전글이 없습니다.댓글