Redux Essentials 학습 노트
Redux Overview and Concepts
위에 도구에 대한 설명 등이 쓰여 있고, 이후에는 계속해서 개념이 쓰여 있다
Terms and Concepts
State Management
state: source of truth
state
에 근거하여 선언적으로 묘사actions: 사용자 입력으로 인한 이벤트에서 변경
state
Terminology
응용 프로그램에서 발생한 이벤트 객체 표시
반환
type
의 함수Reducters:
action
, state
입력 출력 다음 action
함수로state
(이벤트) 기반action
은 사건을 처리하는 사건 청취자라고 느끼게 한다type
은imutable, 비동기적 처리와 부작용 제외응용 프로그램의 현재 상태를 저장하는 변수
state
에서 생성하고 reducer
방법으로 되돌아갈 수 있음getState()
Dispatch:
state
방법을 사용하여 store
를 매개 변수로 변경action
state
의 유일한 수단이다state
실행 방법은 촉발 이벤트로 간주Selectors
dispatch
에서 특정 값을 참조하는 함수Redux App Structure
간단한 계수기를 구체적인 예로 응용하다
Application Contents 섹션
Redux Slices
A "slice"is a collection of Redux reducer logic and actions for a single feature in your app, typically defined together in a single file. The name comes from splitting up the root Redux state object into multiple "slices"of state.
'slice'는 같은 파일에 정의된 프로그램의 한 기능인 Reducter의 논리와 여러 actions의 집합을 가리킨다
예제
reduxjs/redux-essentials-counter-example 창고 보기
src/features/counter/counterSlice.js
import { createSlice } from '@reduxjs/toolkit';
export const slice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
...
export default slice.reducer;
src/app/store.js import { configureStore } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
export default configureStore({
reducer: {
counter: counterReducer,
},
});
상기 예에서 store.state
는'slice'이다import { configureStore } from '@reduxjs/toolkit'
import usersReducer from '../features/users/usersSlice'
import postsReducer from '../features/posts/postsSlice'
import commentsReducer from '../features/comments/commentsSlice'
export default configureStore({
reducer: {
users: usersReducer,
posts: postsReducer,
comments: commentsReducer
}
})
이 예에서 counter
state.users
state.posts
는 각각 독립된'slice'이다.state.comments
'slice'중 하나usersReducer
의 변화를 책임지기 때문에'slice reducter'함수라고 불린다(다른 두 개에도 마찬가지)보태다
API 참조createSlice를 참조하십시오.
상기 예
state.users
에서 다음과 같은 함수는 configureStore
와 다르지만 모두 슬라이스 대상에서 store를 구축한다.import { createSlice, createAction, PayloadAction } from '@reduxjs/toolkit'
import { createStore, combineReducers } from 'redux'
const incrementBy = createAction<number>('incrementBy')
const decrementBy = createAction<number>('decrementBy')
const counter = createSlice({
name: 'counter',
initialState: 0 as number,
reducers: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
multiply: {
reducer: (state, action: PayloadAction<number>) => state * action.payload,
prepare: (value?: number) => ({ payload: value || 2 }), // fallback if the payload is a falsy value
},
},
// "builder callback API", recommended for TypeScript users
extraReducers: (builder) => {
builder.addCase(incrementBy, (state, action) => {
return state + action.payload
})
builder.addCase(decrementBy, (state, action) => {
return state - action.payload
})
},
})
const user = createSlice({
name: 'user',
initialState: { name: '', age: 20 },
reducers: {
setUserName: (state, action) => {
state.name = action.payload // mutate the state all you want with immer
},
},
// "map object API"
extraReducers: {
// @ts-expect-error in TypeScript, this would need to be [counter.actions.increment.type]
[counter.actions.increment]: (
state,
action /* action will be inferred as "any", as the map notation does not contain type information */
) => {
state.age += 1
},
},
})
const reducer = combineReducers({
counter: counter.reducer,
user: user.reducer,
})
const store = createStore(reducer)
store.dispatch(counter.actions.increment())
// -> { counter: 1, user: {name : '', age: 21} }
store.dispatch(counter.actions.increment())
// -> { counter: 2, user: {name: '', age: 22} }
store.dispatch(counter.actions.multiply(3))
// -> { counter: 6, user: {name: '', age: 22} }
store.dispatch(counter.actions.multiply())
// -> { counter: 12, user: {name: '', age: 22} }
console.log(`${counter.actions.decrement}`)
// -> "counter/decrement"
store.dispatch(user.actions.setUserName('eric'))
// -> { counter: 12, user: { name: 'eric', age: 22} }
Creating Slice Reducers and Actions
'slice'의 이름(여기
createStore
과 그 중의 하나인reducter function(이곳"counter"
에서 액션"increment"
을 생성합니다.이 동작을 처리하는 슬라이스 Reducter function도 생성됩니다.
import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
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
Rules of Reducers
reducters는 사용자 정의이지만 다음 규칙을 따라야 합니다.
{type: "counter/increment"}
, state
를 입력으로 다음action
을 계산하고 그 밖의 일을 하지 않는다state
덮어쓰지 않고 복제한 것을 변경한 후 되돌아오기Reducers and Immutable Updates
결론적으로 함수
state
나 createSlice
함수에 Reducter function을 정의하면 간단한 표시로immutable 업데이트를 실현할 수 있다.왜냐하면
createReducer
(과createSlice
는Immer프로그램 라이브러리로 이루어졌기 때문이다.
원래 mutable로 해석됐던 작법에 따라 immutable update의 당의구조를 준비한 것으로 이해할 수 있다는 것이다.
Details of createReducer function
참조API 문서.
이 매개 변수에 의하면
객체
function createSlice({
// A name, used in action types
name: string,
// The initial state for the reducer
initialState: any,
// An object of "case reducers". Key names will be used to generate actions.
reducers: Object<string, ReducerFunction | ReducerAndPrepareObject>
// A "builder callback" function used to add more reducers, or
// an additional object of "case reducers", where the keys should be other
// action types
extraReducers?:
| Object<string, ReducerFunction>
| ((builder: ActionReducerMapBuilder<State>) => void)
})
, 반환 값은대상
{
name : string,
reducer : ReducerFunction,
actions : Record<string, ActionCreator>,
caseReducers: Record<string, CaseReducer>.
getInitialState: () => State
}
.Async Logic with Thunks
Detailed Explation을 읽으면 이해하기 쉬울 것 같아요.
중간부품을 추가하면 일반
createSlice
(JavaScript 대상)과 비동기action
(function) 두 가지를 동시에 처리할 수 있습니다.The React Counter Component
React에서의 사용 방법 정보
React가 내장된 훅
action
useState
을 가지고 있는 것처럼 Redux의 제3자 라이브러리는 각자의 고유한 훅을 가지고 있다.useEffect
쓰기 가능
useSelector
등const count = useSelector(selectCount)
useDispatch
dispatch를 쓰기 위해increment
dispatch(increment))
에서 가져오기const dispatch = useDispatch()
Component State and Forms
Redux store에 데이터를 포함해야 하는지 여부에 대한 판단 기준
Reference
이 문제에 관하여(Redux Essentials 학습 노트), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/tsukker/articles/9cacf9329fa9ba텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)