일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 애그리거트
- react
- 자바
- ACCESS_REFUSED
- 오라클 병렬처리
- exiting abnormally
- Java Reflextion API
- rabbitmq 에러
- REDIS
- 커스텀 로그인
- 네임드 뷰
- 리덕스
- 오라클
- AWS
- forNmae()
- 컴포넌트 주도
- Express
- VUE
- EBS
- 자료구조
- quert
- paraller
- 리액트
- redux
- $emit()
- 도커빌드
- .getClass()
- 트리 회전
- vue.js
- 리덕스 공식문서
- Today
- Total
개발정리
리덕스 예제 따라해보기 본문
상태 관리
작은 리액트 카운터 컴포넌트를 만들어 봅시다.
이것은 컴포넌트 상태의 수를 추적하고 버튼이 클릭 되었을때 숫자를 증가시킵니다.
function Counter(){
//state: a counter value
const [counter,setCounter] = useState(0);
//Action: code that causes an update to the state when something happens
const increment = () => {
setCounter(prevCounter => prevCounter +1);
}
//view: the UI definition
return(
<div>
value: {counter} <button onClick={increment}>Increment</button>
</div>
)
}
이것은 단방향 데이터 흐름의 작은 예제 입니다.
- 상태는 어떤 상황에 어떤 지점에 대한 상태를 나타냅니다.
- UI는 state를 기반으로 렌더링 됩니다.
- 버튼 클릭같은 어떠한 상황이 발생하면 state는 일어난것에 기반하여 업데이트 됩니다.
- ui가 새로운 상태를 기반으로 재 렌더링 됩니다.
하지만, 단순성이 무너질수도 있습니다. 우리가 같은 상태를 공유하는 여러가지의 컴포넌트들을 가질때.
특히 만약 이러한 컴포넌트들이 애플리케이션의 다른 파트에 위치해 있을때.
때로는 부모 컴포넌트로 상태를 넘겨주는것이 해결책 일수 있지만 항상 도움되는것은 아닙니다.
이것을 해결하는 한가지 방법은 컴포넌트로부터 공유하고 있는 state를 추출해서 컴포넌트 트리 바깥의 중앙에 위치한 곳에 놓는것입니다.
이것과 함께, 우리의 컴포넌트 트리는 하나의 큰 "view"가 됩니다. 그리고 어떠한 컴포넌트든 state에 접근할 수 있고 액션을 발생시킬수 있습니다. 그들이 트리의 어디에 있든지 말이죠!
뷰들과 상태들 사이의 독립성을 유지시켜주는 상태 매니지먼트와 강요 정책에 수반되는 개념들을 정의하고 분리하는것에 의해
우리는 우리의 코드에 더 구조적이고 유지보수가 높음을 제공합니다.
이것이 리덕스에 뒤에있는 기본 개념입니다. 당신의 애플리케이션에서 하나의 중앙에 위치한 글로벌 상태를 가지고 다음을 따르는 특정한 패턴들 상태를 업데이트 할때 코드가 예측 가능하도록 하는
불변성
"Mutable"은 "changeable"을 의미합니다. 만약 무언가 "immutable"하다면, 이것은 절대 변하지 않습니다.
자바스크립트에서 객체와 배열들은 기본적으로 mutable입니다. 만약 내가 오브젝트를 하나 만들면, 나는 이것의 필드들을 바꿀수 있습니다.만약 내가 배열을 만들면, 나는 또한 내용물을 바꿀 수 있습니다.
값을 immutably하게 업데이트 하기 위해서, 당신의 코드는 반드시 이미 존재하는 객체나 배열의 복사본을 만들어야 합니다.
그리고 그 복사본을 수정하는 것 입니다.
const obj = {
a: {
// To safely update obj.a.c, we have to copy each piece
c: 3
},
b: 2
}
const obj2 = {
// copy obj
...obj,
// overwrite a
a: {
// copy obj.a
...obj.a,
// overwrite c
c: 42
}
}
const arr = ['a', 'b']
// Create a new copy of arr, with "c" appended to the end
const arr2 = arr.concat('c')
// or, we can make a copy of the original array:
const arr3 = arr.slice()
// and mutate the copy:
arr3.push('c')
리덕스는 모든 state의 업데이트가 immutably하게 되기를 기대합니다.
우리는 어디서 어떻게 중요한지 나중에 살펴볼 것 입니다.
또한 더 쉬운 방법에 대해서도요
카운터 예제 앱의 개념
우리가 살펴볼 샘플 프로젝트는 작은 카운터 애플리케이션입니다.
이것은 우리가 버튼을 통해 숫자를 더하고 빼도록 해줍니다.
이것은 그렇게 익사이팅 하지는 않을 것 입니다.
그러나 이것은 리액트와 리덕스 애플리케이션의 모든 중요한 부분을 보여줍니다.
npx create-react-app redux-essentials-example --template redux
다음과 같은 템플릿을 다운받아 실행 시키면 다음과 같은 카운터 앱을 보실수 있습니다.
이 카운터 앱은 이미 우리가 안에 어떤 동작이 일어나는 지를 볼 수 있도록 해줍니다.
리액트 redux devTool을 이용해 열어보면 카운터라는 state를 발견 하실수 있습니다.
애플리케이션의 구조
- /src
- index.js:애플리케이션의 시작점
- App.js: 리액트의 최상위 컴포넌트
- /app
- store.js:리덕스 store인스턴스를 생성
- /features
- /counter
- counter.js:카운터의 상태를 보여주는 리액트 컴포넌트 UI
- counterSlice.js:리덕스 로직
- /counter
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'
export default configureStore({
reducer: {
counter: counterReducer
}
})
app/store.js 파일을 열어보면 다음과 같습니다.
리덕스 스토어는 리덕스 툴킷의 configureStore함수를 사용하여 만들어 졌습니다.
configureStore는 리듀서의 매개변수로 보낼게 필요합니다.
우리의 애플리케이션은 많은 다른 특징들로 구성되어졌을지도 모릅니다.
그리고 각각의 특징들은 그들 자신의 리듀서 함수를 가지고 있을지도 모릅니다.
우리가 configureStore를 부를때, 우리는 오브젝트안의 다른 리듀서들로 전달할 수 있습니다.
오브젝트안의 key 이름들은 우리의 final state 값 안의 key들을 정의 할 것입니다.
우리는 feature/counter/counterSlice.js 파일을 가지고 있습니다.
이것은 카운터 로직을 위한 reducer함수를 export합니다.
우리는 여기에 counterReducer 함수를 임포트 할 수 있습니다.
그리고 우리가 store를 만들때 포함시킬수 있습니다.
우리가 {counter: counterReducer} 형식으로 오브젝트로 넘길때
이것은 우리는 우리의 리덕스 state 객체에 state.counter 섹션을 가지고 싶다고 말하는 것입니다.
그리고 우리는 counterReducer 함수를 원한다고 하는것입니다. 액션이 dispatch될 때마다
state.counter섹션을 어떻게 업데이트 할 것인지 결정할 책임이 있는
리덕스는 스토어가 다양한 종류의 플러그인과 함께 커스터마이징 되는 것을 허용합니다.
configureStore은 자동적으로 몇몇 미들웨어를 추가합니다.스토어가 개발자에게 좋은 경험을 제공하도록
그리고 또한 리덕스 데브 툴스 확장프로그램이 이 내용을 추적할 수 있도록
Redux Slice
슬라이스는 당신의 앱에 하나의 특징을 위해 액션하는 리덕스 리듀서 로직의 컬렉션 입니다.
전형적으로 한파일에 같이 정의합니다.
우리는 counterReducer함수가 feature/counter/counterSlice.js 로 부터 온다는 것을 알기에 그 파일을 보도록 합시다.
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState:{
value: 0
},
reducers:{
increment: state => {
state.value +=1
},
decrement: state => {
state.value -= 1
},
incrementByAmount: (state,action )=>{
state.value += action.payload
}
}
})
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
앞서서 우리는 다른 버튼을 눌러 세가지 리덕스 액션 타입을 보았습니다.
- {type: "counter/increment"}
- {type: "counter/decrement"}
- {type: "counter/incrementByAmount"}
우리는 액션이라는 것이 type필드를 가진 순수한 객체 라는 것을 압니다.
타입 필드는 항상 문자열이며 우리는 전형적으로 "action creator"함수들을 가지며 이것은 액션 객체를 만들고 리턴합니다.
그럼 어디에 이런 액션 객체들과 타입 문자열 그리고 액션 크리에이터들이 정의되어 있을까요?
우리는 이러한 것들을 매번 직접 작성할 수도 있습니다.
하지만 그것은 아마 지루할 것입니다.
게다가, 리덕스에서 중요한 것은 리덕스 함수와 새로운 상태를 계산하기 위한 논리입니다.
리덕스 툴킷은 createSlice라는 함수를 가지고 있습니다.
이것은 액션 타입 문자열과 액션 크리에이터 함수 그리고 액션 오브젝트를 만드는 일을 합니다.
당신이 해야할 것은 slice를 위한 이름을 정의하고 리듀서 함수들을 가진 객체를 작성 하는 것이며 이것은 이에 상응하는 액션 코들를 자동적으로 만들어 냅니다.
name옵션의 문자열은 각 액션 타입의 첫번째 파트로 사용됩니다.
그리고 각 리듀서 함수의 키 이름은 두번째 파트로 사용됩니다.
그러므로, "counter"라는 이름 + "increment" 리듀서 함수는 액션을 생성합니다.
타입을 "{type: "counter/increment"}" 로 가진
덧붙여서, name필드에는 createSlice는 필요합니다. 리듀서들을 위한 초기 상태를 전달하는 것이 필요합니다.
그러므로 이것이 호출되면 처음엔 state가 있습니다.
우리는 여기서 세가지 리듀서 함수들을 볼수 있습니다.
그리고 각각 함수들은 다른 액션 타입에 상응합니다.
..............................................................................
리덕스 스토어 생성하기
참고
https://ko.redux.js.org/tutorials/essentials/part-1-overview-concepts
Redux 핵심, Part 1: Redux Overview and Concepts | Redux
The official Essentials tutorial for Redux: learn how to use Redux, the right way
ko.redux.js.org
https://ko.redux.js.org/tutorials/essentials/part-2-app-structure/
Redux 핵심, Part 2: Redux App Structure | Redux
The official Redux 핵심 튜토리얼: learn the structure of a typical React + Redux app
ko.redux.js.org
'React.js' 카테고리의 다른 글
스토리북 - 스토리가 뭐야? (0) | 2024.08.22 |
---|---|
스토리북에 대하여... (0) | 2024.08.22 |
리덕스에 대하여 (0) | 2024.06.29 |
useReducer (0) | 2024.01.30 |
useMemo (0) | 2024.01.13 |