-
React - 컴포넌트 리렌더링 방지(React.memo)React 2020. 9. 11. 13:29
컴포넌트의 리렌더링 성능 최적화
export default React.memo(UserList);
컴포넌트 내보낼 때 React.memo() 로 감싸주면 됨
CreateUsers도 마찬가지
-> UserList.js의 User 컴포넌트는 한 파일에 있는 또 다른 컴포넌트이기 때문에 함수 자체를 React.memo로 감싸준다
const User = React.memo(function User({ user, onRemove, onToggle }){ const {username, email, id, active} = user; useEffect(() => { console.log(user); return () => { console.log('user 값이 바뀌기 전'); console.log(user); } }, [user]); return ( <div> <b style={{ color: active ? 'green': 'black', cursor: 'pointer' }} onClick={() => onToggle(id)} > {username} </b> <span>({email})</span> <button onClick={() => onRemove(id)}>삭제</button> </div> ); });
- App.js -
App.js의 JSX 를 보면 onRemove() onToggle() 등이 바뀔 때, UserList.js의 내용과 User컴포넌트의 내용도 바뀌게 된다.
-> 입력할 때마다 모든 컴포넌트들 리렌더링 됨
-> 해결위해서 App.js의 onCreate(), onRemove(), onToggle() 함수가 기존 users를 참조하지 않게 해야한다.
=> useState의 함수형 업데이트 사용
const onCreate = useCallback(() => { const user = { id: nextId.current, username, email, }; setUsers(users => users.concat(user)); setInputs({ username: '', email: '' }); console.log(nextId.current); nextId.current += 1; }, [username, email]);
이러면 deps에서도 users 쓸 필요 없이, username과 email이 바뀔 때만 onCreate함수 호출된다.
나머지도 동일한 방식으로
const onRemove = useCallback(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 )); }, []);
React.memo의 두번째 파라미터 사용
- UserList.js -
export default React.memo(UserList, (prevProps, nextProps) => nextProps.users === prevProps.users);
이전 props와 다음 props가 같다면 리렌더링 하지 않겠다는 뜻
이전 코드
- App.js -
import React, { useRef, useState, useMemo, useCallback } from 'react'; import UserList from './UserList'; import CreateUser from './CreateUser'; function countActiveUsers(users){ console.log('활성 사용자 수를 세는 중...'); 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, [name]: value }); }, [inputs]); const [users, setUsers] = useState([ { id: 1, username: 'starters', email: 'public.starters@gmail.com', active: true, }, { id: 2, username: 'tester', email: 'tester@gmail.com', active: false, }, { id: 3, username: 'jajajojo', email: 'jajajojo@gmail.com', active: false, } ]); const nextId = useRef(4); const onCreate = useCallback(() => { const user = { id: nextId.current, username, email, }; setUsers(users.concat(user)); setInputs({ username: '', email: '' }); console.log(nextId.current); nextId.current += 1; }, [username, email, users]); const onRemove = useCallback(id => { setUsers(users.filter(user => user.id !== id)) }, [users]); const onToggle = useCallback(id => { setUsers(users.map( user => user.id === id ? { ...user, active: !user.active } : user )); }, [users]); 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;
- CreateUser.js -
맨 아랫줄에 React.memo만 없음
- UserList.js -
import React, { useEffect } from 'react'; function User({ user, onRemove, onToggle }){ const {username, email, id, active} = user; useEffect(() => { console.log(user); return () => { console.log('user 값이 바뀌기 전'); console.log(user); } }, [user]); return ( <div> <b style={{ color: active ? 'green': 'black', cursor: 'pointer' }} onClick={() => onToggle(id)} > {username} </b> <span>({email})</span> <button onClick={() => onRemove(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 UserList;
'React' 카테고리의 다른 글
React - App 컴포넌트에서 useReducer사용 (0) 2020.09.11 React - useReducer (0) 2020.09.11 React - 함수 재사용(useCallback) (0) 2020.09.11 React - 연산한 값 재사용(useMemo) (0) 2020.09.11 React - useEffect Hook (0) 2020.09.11