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를 매개 변수로 변경actionstate의 유일한 수단이다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
}
})
이 예에서 counterstate.usersstate.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가 내장된 훅
actionuseState을 가지고 있는 것처럼 Redux의 제3자 라이브러리는 각자의 고유한 훅을 가지고 있다.useEffect쓰기 가능
useSelector등const count = useSelector(selectCount)useDispatchdispatch를 쓰기 위해incrementdispatch(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.)