분류 Reactjs

React State

컨텐츠 정보

  • 조회 305 (작성일 )

본문

State in React는 React를 배울 때 가장 중요한 주제 중 하나입니다. 상태 호흡은 React 애플리케이션에 실시간으로 적용됩니다. 사용자가 상호 작용할 수 있기 때문에 웹 사이트에 표시되는 정적 콘텐츠를 넘어 응용 프로그램을 확장시키는 것입니다. 사용자와 응용 프로그램을 상호 작용할 때마다 기본 상태가 변경되어 상태가 나타내는 UI가 변경 될 수 있습니다.


https://www.robinwieruch.de/react-state 


이 광범위한 연습에서는 React에서 상태 관리의 모든 가능성을 안내합니다. 우리는 React 구성 요소에 배치 된 간단한 상태 관리부터 시작하여 React Hooks를 통해 모든 기능을 탐색하고 React 자체 또는 타사 라이브러리가 관리하는 React에서 더 복잡한 전역 상태로 끝날 것입니다.


React 연습에서 이 상태 관리를 수행 한 후에는 React의 상태를 잘 파악해야 합니다. 아마도 이것을 넘어 서면 다음 React 애플리케이션의 이상적인 시나리오에서 상태를 관리하는 방법에 대한 좋은 아이디어를 얻을 수 있습니다.

  • What is State in React?
  • React State: useState
  • React State: useReducer
  • React State: useContext
  • Local vs Global State
  • React State: Redux
  • Origin of State
  • React State: GraphQL
  • React State: this.state and setState (Legacy)

상태는 무엇입니까? 


프론트 엔드 애플리케이션의 UI는 해당 상태를 나타냅니다. 상태는 단지 스냅샷입니다. 사용자가 애플리케이션과 상호 작용하여 상태를 변경하면 UI는 이전 상태가 아닌 이 새로운 상태로 표시되므로 나중에 완전히 다르게 보일 수 있습니다.


State => UI 


상태는 여러 가지가 될 수 있습니다.

1) UI에 대화 상자 / 모달 / 팝 오버 구성 요소가 열리거나 닫혔음을 알리는 부울입니다.

2) 현재 로그인 한 애플리케이션 사용자를 반영하는 사용자 객체.

3) React에서 가져와 UI에 표시되는 원격 API (예 : 객체 / 사용자 목록)의 데이터


State는 JavaScript 프리미티브와 객체로 상태를 나타내는 JavaScript 데이터 구조에 대한 또 다른 멋진 단어입니다. 예를 들어, 간단한 상태는 JavaScript 부울 일 수 있지만 보다 복잡한 UI 상태는 JavaScript 객체 일 수 있습니다.


// 1)
const isOpen = true;
// 2)
const user = {
id: '1',
firstName: 'Robin',
lastName: 'Wieruch',
email: 'hello@robinwieruch.com',
};
// 3)
const users = {
2: {
firstName: 'Dennis',
lastName: 'Wieruch',
email: 'hello@denniswieruch.com',
},
3: {
firstName: 'Thomas',
lastName: 'Wieruch',
email: 'hello@thomaswieruch.com',
},
};

이러한 모든 상태는 주로 세 가지 작업을 수행하는 단일 React 구성 요소로 관리 할 수 ​​있습니다.


A) 상태 저장

B) 사용자가 상태를 수정할 수 있게 함

C) 상태가 변경되면 UI 업데이트


이것은 React Hooks가있는 React 컴포넌트 내에서 수행 할 수 있습니다. 여기서는 후크를 사용하여 React 구성 요소와 같은 위치에 있기 때문에 여기에서 말합니다. 나중에 전역 및 React 구성 요소 외부에서 관리되는 다른 상태에 대해 학습합니다. 상태에 대한 React Hooks를 먼저 살펴 보자.


REACT STATE: USESTATE 


React의 useState 후크는 많은 React 초보자가 React에서 처음으로 상태를 만난다는 것입니다.


import React from 'react';
const App = () => {
const [counter, setCounter] = React.useState(42);
const handleClick = () => {
setCounter(counter + 5);
};
return (
<>
<p>{counter}</p>
<button type="button" onClick={handleClick}>
Increase by 5
</button>
</>
);
};

useState 후크는 React 컴포넌트가 처음 렌더링 될 때만 초기 상태를 인수로 사용하고 현재 상태와 상태 업데이트 함수라는 두 값을 가진 배열을 리턴합니다. 현재 상태는 React 컴포넌트 내 어딘가에 표시하는 데 사용되는 반면, 상태 업데이트 기능은 현재 상태를 변경하는 데 사용됩니다 (예 : HTML 버튼 onClick).


한 단계 더 나아가서 정수를 늘리는 데 사용할 수 없으며 입력 할 때 입력 HTML 요소의 동적 상태를 캡처하는 데 사용할 수 있습니다. 입력 HTML 요소는 현재 상태를 값으로 사용하므로 제어되는 구성 요소 / 요소가 됩니다. 내부 HTML은 더 이상 상태를 관리하지 않지만 React의 상태 관리는 다음과 같습니다.


import React from 'react';
const App = () => {
const [text, setText] = React.useState('Hello React');
const handleChange = event => {
setText(event.target.value);
};
return (
<>
<p>{text}</p>
<input type="text" value={text} onChange={handleChange} />
</>
);
};

결국 React의 useState는 React를 사용하여 상태 관리에 대한 관문입니다. 여기에서 오는 모든 것이 더 강력하지만 더 복잡합니다.


REACT STATE: USEREDUCER 


React의 useReducer는 JavaScript Reducer의 개념에서 파생됩니다. 아이디어 : 감속기 함수는 현재 상태와 페이 로드가 있는 작업을 가져 와서 새로운 상태로 계산합니다.


(state, action) => newState 


감속기 기능은 할 일 항목 목록의 상태와 전체 상태를 관리하기 위해 다음과 같이 보일 수 있습니다.


const todoReducer = (state, action) => {
switch (action.type) {
case 'DO_TODO':
return state.map(todo => {
if (todo.id === action.id) {
return { ...todo, complete: true };
} else {
return todo;
}
});
case 'UNDO_TODO':
return state.map(todo => {
if (todo.id === action.id) {
return { ...todo, complete: false };
} else {
return todo;
}
});
default:
return state;
}
};

들어오는 조치의 유형에 따라 스위치 케이스 중 하나가 할 일 항목을 완료하거나 완료하지 않은 것으로 간주됩니다. 액션의 페이로드 (여기서 id 속성)는 목록에서 어떤 할일 항목 (상태 자체)을 토글해야 하는지 감속기에게 알려줍니다. 다른 모든 할 일 항목은 변경되지 않습니다.


이제 React 컴포넌트의 다음 초기 상태를 고려하십시오.


const initialTodos = [
{
id: 'a',
task: 'Learn React',
complete: false,
},
{
id: 'b',
task: 'Learn Firebase',
complete: false,
},
];

React의 useReducer 후크와 함께 이 감속기 기능을 사용하는 React 구성 요소는 다음과 같습니다.


const App = () => {
const [todos, dispatch] = React.useReducer(
todoReducer,
initialTodos
);
const handleChange = todo => {
dispatch({
type: todo.complete ? 'UNDO_TODO' : 'DO_TODO',
id: todo.id,
});
};
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
<label>
<input
type="checkbox"
checked={todo.complete}
onChange={() => handleChange(todo)}
/>
{todo.task}
</label>
</li>
))}
</ul>
);
};

이 시나리오에서는 개별 항목을 완료 또는 완료로 토글 할 수 있는 초기 할 일 항목 목록 만 있습니다. useReducer 후크는 React 구성 요소가 처음 렌더링 될 때만 이전에 정의 된 리듀서와 초기 상태를 인수로 가져 와서 현재 상태와 상태 업데이트 함수라는 두 값을 가진 배열을 리턴합니다.


React의 useState 후크와 달리 useReducer 후크의 상태 업데이트 함수는 항상 조치를 인수로 취합니다. 일반적으로 디스패치라고 합니다. 액션을 리듀서에 "패치"하기 때문입니다. 각 작업에는 감속기 기능에서 나중에 사용되는 필수 유형 속성과 여기에 할 일 항목의 id 속성 인 추가 페이 로드가 있습니다.


useReducer 또는 useState를 언제 사용해야 합니까? 일반적으로 말하자면 (A) 상태 전이가 더 복잡해지면 (B) 상태 객체가 더 이상 단순한 JavaScript 프리미티브가 아니거나 (C) 여러 상태 인 경우 React의 useReducer 후크를 React의 useState 후크보다 사용할 수 있습니다. 조건부로 서로 관련되어 있습니다. 당연히 이것은 React 애플리케이션이 소규모 프로젝트를 넘어 성장할 때 발생합니다.


REACT STATE: USECONTEXT 


기술적으로 React의 useContext 후크는 state와 관련이 없습니다. 소품을 컴포넌트 트리 아래로 전달하는 것이 더 편리합니다. 일반적으로 React props은 부모에서 자식 구성 요소로 전달됩니다. 그러나 React의 Context API를 사용하면 그 사이에 React 구성 요소를 터널링 할 수 있습니다. 따라서 체인 사이에 다른 React 구성 요소를 방해하지 않고 할아버지 구성 요소에서 손자 구성 요소로 props을 전달할 수 있습니다.


그러나 React의 Context API 메커니즘은 실제로 React의 고급 상태 관리에 사용됩니다. 많은 React 구성 요소를 통해 현재 상태 및 useState 또는 useReducer에서 반환 된 상태 업데이트 기능을 터널링 합니다. 이런 식으로 개발자는 useReducer / useState를 사용하여 최상위 컴포넌트에서 React 상태를 관리하기 시작했고 이 상태에 관심이 있거나 이를 업데이트하는 모든 React 하위 컴포넌트에 useContext를 사용하여 반환 된 값 (현재 상태 및 상태 업데이트 함수)을 전달했습니다. 상태.


const App = () => {
const [filter, dispatchFilter] = useReducer(filterReducer, 'ALL');
const [todos, dispatchTodos] = useReducer(todoReducer, initialTodos);
const filteredTodos = todos.filter(todo => {
...
});
return (
<TodoContext.Provider value={dispatchTodos}>
<Filter dispatch={dispatchFilter} />
<TodoList todos={filteredTodos} />
<AddTodo />
</TodoContext.Provider>
);
};

이전 코드 스니펫에서 dispatchTodos 업데이트 프로그램 기능으로 할 일 항목을 수정하는 기능은 React의 Context API를 통해 전 세계적으로 제공됩니다. 다른 단계에서 React의 useContext 후크는 모든 하위 컴포넌트에서 디스패치 기능을 검색하는 데 사용될 수 있습니다. 이 섹션의 연습을 따라 이 개념을 자세히 살펴보십시오.


useContext를 useReducer 또는 useState와 결합 할 때 


1) 일반적으로 React의 useContext 훅은 React의 useState 훅 및 / 또는 useReducer 훅과 함께 사용해야 합니다.

2) 전략적으로 말하면 React의 useContext 후크는 상태를 로컬 상태에서 전역 상태로 옮기는 데 사용할 수 있습니다. 상태는 최상위 수준의 구성 요소에서 전역 적으로 관리되지만 React의 useContext 후크는 상태 및 상태 업데이트 프로그램 기능을 관심 있는 모든 하위 구성 요소에 전달하는 데 사용됩니다. 이에 대한 자세한 내용은 나중에 읽으십시오.


LOCAL VS GLOBAL STATE 


다음은 React에서 상태 관리를 위한 세 가지 주요 전략입니다.


(1) React 컴포넌트 내에서 상태를 관리합니다.

(2) 모든 하위 구성 요소에 분배 되는 최상위 React 구성 요소 내에서 상태를 관리하십시오.

(3) 타사 상태 관리 라이브러리를 사용하여 React 외부의 상태를 관리하십시오.


세 가지 전략 모두 다음 유형의 상태에 매핑됩니다.


(1) 지역 상태

(2) 글로벌 상태이지만 React에서 관리

(3) 글로벌 상태, 타사 상태 관리 라이브러리에서 관리


또한, 세 가지 전략을 모두 활성화하면 React의 기능 내외에서 다양한 기능 또는 이러한 기능의 조합으로 매핑됩니다.


(1) useState 및 useReducer

(2) useContext를 가진 useState / useReducer

(3) Redux, MobX 및 기타 다양한 상태 관리 라이브러리


귀하는 이러한 전략 중 하나에 만 국한되지 않습니다. 더 작은 애플리케이션은 useState 및 useReducer 후크를 사용하여 React 컴포넌트에서 상태를 관리하는 것으로 시작하는 반면, 점점 증가하는 애플리케이션 개발자는 둘 이상의 React 컴포넌트가 필요로 하는 상태와 공유해야 하는 상태에 대해 전체적으로 상태를 관리하기 시작합니다. 다수의 React 컴포넌트.


전략적으로 React의 useReducer + useContext hooks (2)는 전략 (3)의 Redux와 같은 자체 상태 관리 라이브러리를 만들 수 있게 합니다.


const App = () => {
const [state, dispatch] = useCombinedReducers({
filter: useReducer(filterReducer, 'ALL'),
todos: useReducer(todoReducer, initialTodos),
});
...
};

이 섹션의 연습에서 useCombinedReducers와 함께 이러한 구현을 살펴 보겠습니다.


REACT STATE: REDUX 


React의 useReducer는 Redux 이후에 세상에 왔지만 그 개념은 Redux 자체에서 비롯되었습니다. Redux는 다른 수준에서 상태 관리를 수행합니다. 국가가 React 외부의 외부 세력에 의해 전 세계적으로 관리되고 있다고 말할 수도 있습니다.


React => Action => Reducer(s) => Store => React 


반면 Action => Reducer (s) => Store는 Redux를 캡슐화합니다. JS에서 Redux의 모든 부분을 간단히 요약 해 봅시다. 이것은 Redux 라이브러리에 전혀 의존하지 않는 두 가지 Redux 동작에 작용하는 Redux Reducer입니다.


function reducer(state, action) {
switch(action.type) {
case 'TODO_ADD' : {
return applyAddTodo(state, action);
}
case 'TODO_TOGGLE' : {
return applyToggleTodo(state, action);
}
default : return state;
}
}
function applyAddTodo(state, action) {
return state.concat(action.todo);
}
function applyToggleTodo(state, action) {
return state.map(todo =>
todo.id === action.todo.id
? { ...todo, completed: !todo.completed }
: todo
);
}

Redux Reducer에 대해 알고있는 Redux 상점 :


import { createStore } from 'redux';
const store = createStore(reducer, []);

그런 다음 Redux Store는 작은 API 표면을 제공하여 상호 작용합니다 (예 : Redux 액션 발송 :


store.dispatch({
type: 'TODO_ADD',
todo: { id: '0', name: 'learn redux', completed: false },
});

마지막으로 JavaScript에서 Redux Store를 사용하여 변경 사항을 들을 수 있습니다.


store.subscribe(() => {
console.log(store.getState());
});

Redux는 Action, Reducer, Store와 같은 모든 조각으로 요약됩니다. 상점 구독을 React에 첨부하면 Redux의 상태가 변경 될 때마다 React UI가 업데이트 될 수 있습니다.


Redux의 또 다른 인기 있는 대안은 React의 상태에 대한 MobX입니다. 두 상태 관리 라이브러리 모두 React 초기에 매우 인기가 있었습니다. 그러나 더 가벼운 상태 관리 솔루션을 제공함으로써 두 가지 타이탄과 경쟁하는 다른 상태 관리 라이브러리가 있습니다.


ORIGIN OF STATE 


모든 종류의 상태를 동일하게 만드는 것은 한 상태에서 다른 상태로의 천이 특성입니다. 그러나 프런트 엔드 응용 프로그램의 상태 원점은 다릅니다. 상태는 클라이언트 응용 프로그램 (프론트 엔드) 또는 원격 서버 응용 프로그램 (백 엔드)에서 시작될 수 있습니다.


예를 들어 클라이언트 응용 프로그램 내에서 시작된 상태는 열린 / 닫힌 대화 상자 구성 요소의 상태에 대한 부울 플래그 일 수 있습니다. 클라이언트 응용 프로그램은 초기 상태 (예 : 닫힌 대화 상자)를 정의하고 상태 전이 + 실제 가능한 상태 (예 : 부울 플래그가 false 또는 true로 설정 됨)를 정의합니다.

  • Dialog, Dropdown, Popover 및 DatePicker 구성 요소의 열기 / 닫힘 상태입니다.
  • 드롭 다운 구성 요소에서 선택된 항목.
  • 테이블 구성 요소의 필터 / 정렬 상태.
  • InputField 구성 요소의 텍스트

반대로, 상태가 원격 서버 응용 프로그램에서 시작된 경우 클라이언트 응용 프로그램에서 초기 상태 및 전환이 정의 될 수 있습니다 (예 : 초기 상태는 null이지만 일단 데이터가 API에서 도착하면 상태는 실제 데이터로 설정되지만 백엔드 응용 프로그램에서 오는 가능한 상태는 클라이언트 응용 프로그램에서 예측할 수 없습니다.

  • 원격 API에서 오는 사용자 목록.
  • 현재 원격 API에서 온 로그인 한 사용자입니다.

왜 이것에 대해 알아야 합니까? 클라이언트 애플리케이션 내에서 발생하는 상태 관리는 백엔드 애플리케이션에서 오는 상태를 관리하는 것보다 관리하기 쉬운 경향이 있습니다. 클라이언트 응용 프로그램에서 시작된 관리 상태는 다음 세 가지 전략 모두를 통해 달성 할 수 있습니다.

(1) useState 및 useReducer

(2) useContext를 가진 useState / useReducer

(3) Redux, MobX 및 기타 다양한 상태 관리 라이브러리


후자는 서버 응용 프로그램에서 시작된 관리 상태가 더 복잡한 경향이 있습니다. 데이터 (예 : null) 또는 실제 채워진 데이터 상태 뿐만 아니라 오류 및 진행 상태에 대한 추가 상태와 함께 제공됩니다. 또한 선택한 전략으로 이러한 모든 상태를 설정하는 것은 반복적인 프로세스이며 캐싱 및 부실 상태와 같은 고급 주제를 고려하면 큰 고통입니다. 그것은 많은 고통 포인트와 함께 제공됩니다.


바로 다른 기술인 GraphQL이 사용됩니다.


REACT STATE: GRAPHQL 


GraphQL은 상태와 밀접한 관련이 없습니다. GraphQL은 클라이언트-서버 통신을 위한 REST의 대안입니다. 그러나 React 애플리케이션에 적합한 GraphQL 라이브러리를 사용하면 서버 애플리케이션에서 시작된 상태 관리가 훨씬 간단 해집니다.


예를 들어, Apollo Client는 이러한 GraphQL 클라이언트 라이브러리 중 하나입니다. GraphQL 쿼리 및 돌연변이를 통해 원격 GraphQL API에서 데이터를 읽고 쓰는 데 사용할 수 있습니다. 예를 들어, React 구성 요소 내에서 Apollo로 데이터를 읽는 쿼리를 사용하면 다음과 같이 보일 수 있습니다.


import React from 'react';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';
const GET_CURRENT_USER = gql`
{
viewer {
login
name
}
}
`;
const Profile = () => (
<Query query={GET_CURRENT_USER}>
{({ data, loading }) => {
if (data.viewer) {
return null;
}
if (loading) {
return <div>Loading ...</div>;
}
return (
<div>
{data.viewer.name} {data.viewer.login}
</div>
);
}}
</Query>
);
export default Profile;

GraphQL이 GraphQL 쿼리를 정의하는 데 사용되었지만 Apollo Client의 Query 구성 요소는 UI에서 전체 데이터 페치 프로세스를 나타내는 데 필요한 모든 상태를 제공합니다. 이 경우 데이터와 로드 상태를 제공하지만 오류 상태 등에 액세스 할 수도 있습니다. 모든 상태 전이를 직접 작성할 필요는 없으며 Apollo Client GraphQL 라이브러리에 그대로 두십시오.


또한 캐싱은 고급 GraphQL 클라이언트 라이브러리에서 처리됩니다. 데이터가 이미 존재하고 캐시 되어 있기 때문에 오래된 데이터를 피하고 불필요한 데이터 페치 절차를 피하는 데 도움이 되는 여러 가지 고급 기능이 있습니다.


이제 클라이언트 및 서버 응용 프로그램에서 시작된 상태를 알면 다음과 같은 방법으로 책임을 분할하여 두 원본을 구분하는 가장 좋은 솔루션이 될 수 있습니다.


  • 클라이언트 원산지 상태 관리 솔루션
    useState / useReducer + useContext / Redux / MobX
  • 서버 원산지 상태 관리 솔루션
    GraphQL + powerful GraphQL library

많은 React 응용 프로그램의 경우 GraphQL과 강력한 GraphQL 클라이언트 라이브러리를 사용하여 서버 시작 상태를 수용하면 상태 관리가 쉬워집니다. 남은 것은 React의 Hooks로 쉽게 관리 할 수 있는 UI 상태입니다. 더 이상 Redux가 필요하지 않습니다.


REACT STATE: THIS.STATE AND SETSTATE (LEGACY) 


React 클래스 컴포넌트를 사용하지 않고 React 함수 컴포넌트만 사용하는 경우 여기에서 더 이상 읽을 필요가 없습니다. 여전히 React Class Components를 사용하고 있다면

다음 예제는 React 클래스 구성 요소에서 상태를 관리하는 방법을 보여줍니다.


class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
};
}
onChange = event => {
this.setState({ value: event.target.value });
};
render() {
return (
<div>
<h1>Hello React ES6 Class Component!</h1>
<input
value={this.state.value}
type="text"
onChange={this.onChange}
/>
<p>{this.state.value}</p>
</div>
);
}
}

어느 쪽이든 클래스 구성 요소 및 함수 구성 요소에서 상태를 관리 할 수 ​​있습니다. 그러나 React Function Components의 React Hook 만 사용하면 React에서 보다 현대적이고 강력한 상태 관리 솔루션을 사용할 수 있습니다. React Hooks와 GraphQL의 결합은 React에서 상태를 길들이기 위한 궁극적 인 조합 일 수 있습니다.