(TIL 16일차) React (5)

pks787·2020년 2월 13일
0

TIL(Today I Learned)

목록 보기
9/43

UseMemo

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;
  • 성능 최적화를 위하여 연산된 값을 재사용하는 방법
  • users 에 변화가 있을때만 변화 해야 하는데, input 값이 바뀔 때에도 컴포넌트가 리렌더링 되므로 이렇게 불필요할때에도 호출하여서 자원이 낭비
  • useMemo 의 첫번째 파라미터에는 어떻게 연산할지 정의하는 함수
  • 두번째 파라미터에는 deps 배열(배열 안의 내용이 바뀌면 등록한 함수 호출해서 연산, 바뀌지 않으면 이전 연산한 값 재사용)

UseCallBack

  const onRemove = id => {
    setUsers(users.filter(user => user.id !== id));
  };

  // 위 코드를 아래와 같이 변경
   const onRemove = useCallback(
    id => {
      setUsers(users.filter(user => user.id !== id));
    },
    [users]
  );
  • useMemo와 비슷한 Hook
  • useMemo는 특정 결과 값을 재사용할 때 사용
  • useCallback은 특정 함수를 만들지 않고 재사용
  • 함수 안에서 사용하는 상태 혹은 props 가 있다면 꼭, deps 배열안에 포함시켜야 함
  • useCallback은 useMemo 기반으로 만들어짐

React.memo

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); // 이와 같이 작성
  • 컴포넌트의 props가 바뀌지 않는다면 리렌더링 방지하여 성능 최적화를 해줌
  • 컴포넌트에서 리렌더링이 필요한 상황에서만 설정

Tip

  • 리액트 개발 시, useCallback, useMemo, React.memo 는 컴포넌트의 성능을 실제로 개선할수있는 상황에서만 사용❗
  • 렌더링 최적화 하지 않을 컴포넌트에 React.memo 를 사용하는것은, 불필요한 props 비교만 하는 것이기 때문에 실제로 렌더링을 방지할수있는 상황이 있는 경우에만 사용

useReducer

function reducer(state, action) { 
  // 새로운 상태를 만드는 로직
  // const nextState = ...
  return nextState;
}
function Counter() {
  const [number, dispatch] = useReducer(reducer, 0);
}


// 사용 예시
function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

function Counter() {
  const [number, dispatch] = useReducer(reducer, 0);

  const onIncrease = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const onDecrease = () => {
    dispatch({ type: 'DECREMENT' });
  };

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}
// 새 할 일을 등록하는 액션
{
  type: 'ADD_TODO',
  todo: {
    id: 1,
    text: 'useReducer 배우기',
    done: false,
  }
}
  • 현재 상태와 액션 객체를 파라미터로 받아와서 새로운 상태를 반환해주는 함수
  • action 은 업데이트를 위한 정보, 보통 type 값을 지닌 객체 형태로 사용
  • 상태 업데이트 로직을 컴포넌트 바깥에 작성 할 수도 있고, 심지어 다른 파일에 작성 후 불러와서 사용
const [state, dispatch] = useReducer(reducer, initialState);

dispatch({ type: 'INCREMENT' })
  • state 는 우리가 앞으로 컴포넌트에서 사용 할 수 있는 상태
  • dispatch 는 액션을 발생시키는 함수e
  • 첫번째 파라미터는 reducer 함수이고, 두번째 파라미터는 초기 상태
function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

useReducer vs useState

const [value, setValue] = useState(true);
  • 컴포넌트에서 관리하는 값이 딱 하나고, 그 값이 단순한 숫자, 문자열 또는 boolean 값이라면 확실히 useState 로 관리
setUsers(users => users.concat(user));
setInputs({
  username: '',
  email: ''
});
  • setter 를 한 함수에서 여러번 사용해야 하는 일이 발생하는 경우

Context API

function UserList({ users, onRemove, onToggle }) {
  return (
    <div>
      {users.map(user => (
        <User
          user={user}
          key={user.id}
          onRemove={onRemove}
          onToggle={onToggle}
        />
      ))}
    </div>
  );
}
  • 위의 코드 처럼 UserList 컴포넌트는 메소드를 연결해주는 중간다리 역할
  • 실제로 UserList 컴포넌트에서 메소드를 사용하지 않음
  • Context API를 dispatch와 함께 사용하면 이러한 문제 해결
  • 프로젝트 안에 전역적으로 값을 관리하며, 값은 외부 라이브러리 인스턴스, DOM으로 설정 가능
  • React.createContext() 사용
const UserDispatch = React.createContext(null); // 선언 및 기본값 설정
import { UserDispatch } from './App'; // 나중에 이렇게 불러와서 사용 가능

// UserDispatch 라는 이름으로 내보내줍니다.
export const UserDispatch = React.createContext(null);

// Provider를 이용해 값 설정
<UserDispatch.Provider value={dispatch}>...</UserDispatch.Provider>

  • 위의 처럼 파라미터 안에 기본값 설정
  • Context를 만들면 안에 Provider라는 컴포넌트가 들어 있는데, 이것을 통해 값 설정 가능하며 Provide안에 감싸진 어느 컴포넌트 안에서 Context 값 접근 가능

profile
Front End. Dev

0개의 댓글