*** 포스팅 목적이 아닌 기록/공부 목적으로 작성한 글이라, 건너뛴 부분이 많습니다!
# 필요한 코드만 요약
- package.json
"scripts": {
"postinstall": "rndebugger-open"
}
- 설치
$ yarn add redux react-redux @reduxjs/toolkit redux-devtools-extension redux-thunk
$ yarn add react-native-debugger-open --save-dev
$ yarn postinstall
*** 최종코드
import {createStore, applyMiddleware} from 'redux';
import {createSlice} from '@reduxjs/toolkit';
import {composeWithDevTools} from 'redux-devtools-extension';
import thunk from 'redux-thunk';
const initialState = {
isLoaded: false,
};
const slice = createSlice({
name: 'reducer',
initialState,
reducers: {
setIsLoadedReducer: (state, action) => {
state.isLoaded = action.payload;
},
},
});
export const {setIsLoadedReducer} = slice.actions;
export const setIsLoadedAsync = (isLoaded: boolean) => {
return async (dispatch, getState) => {
try {
console.log('왔으');
dispatch(setIsLoadedReducer(isLoaded));
} catch (error) {
// notiE
}
};
};
const store = createStore(
slice.reducer,
composeWithDevTools(applyMiddleware(thunk)),
);
export default store;
import React from 'react';
import {connect} from 'react-redux';
import {setIsLoadedAsync} from '../redux/store';
const Text = styled.Text``;
const Test = props => {
const {isLoaded, setIsLoaded} = props;
const handleToggle = () => {
setTimeout(() => setIsLoaded(!isLoaded), 1000);
// setIsLoadedAsync(!isLoaded);
};
return (
<Container>
<Button onPress={handleToggle}>
<Text>toggle</Text>
</Button>
<Text>{isLoaded ? 'loaded' : 'loading...'}</Text>
</Container>
);
};
const mapStateToProps = state => {
return {
isLoaded: state.isLoaded,
};
};
const mapDispatchToProps = dispatch => {
return {
setIsLoaded: (isLoaded: boolean) => dispatch(setIsLoadedAsync(isLoaded)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Test);
원리 파헤치자
1) 기본 + 개발툴
import {createStore} from 'redux';
import {composeWithDevTools} from 'redux-devtools-extension';
export const SET_IS_LOADED = 'SET_IS_LOADED';
const initialState = {
setIsLoaded: false,
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case SET_IS_LOADED:
console.log('SET_IS_LOADED', action);
return {...state, isLoaded: action.isLoaded};
default:
return state;
}
};
const store = createStore(reducer, composeWithDevTools(applyMiddleware()));
export default store;
const {isLoaded} = store.getState();
const handleToggle = () => {
store.dispatch({type: SET_IS_LOADED, isLoaded: true});
};
직접 store. 해주기
2) map~ToProps, actionCreators 만들어주기
const setIsLoaded = (isLoaded: boolean) => ({
type: SET_IS_LOADED,
isLoaded,
});
export const actionCreators = {
setIsLoaded,
};
const mapStateToProps = state => {
return {
isLoaded: state.isLoaded,
};
};
const mapDispatchToProps = dispatch => {
return {
setIsLoaded: (isLoaded: boolean) =>
dispatch(actionCreators.setIsLoaded(isLoaded)),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Test);
그럼 props에서 얘네 쓸 수 있으~
3-1) toolkit: createAction
2) 의 첫번째 setIsLoaded 대신
import {createAction} from '@reduxjs/toolkit';
const setIsLoaded = createAction('SET_IS_LOADED');
그리고 case에서 .type으로 바꾸고 .payload로 바꾸기
const reducer = (state = initialState, action) => {
switch (action.type) {
case setIsLoaded.type: // this!!
return {...state, isLoaded: action.payload}; // this!! payload
default:
return state;
}
};
3-2) toolkit: createReducer
원래 reducer 대신
const reducer = createReducer(initialState, {
[setIsLoaded]: (state, action) => {
state.isLoaded = action.payload; // 이렇게 mutate를 할 수 있지!!!!!
},
});
원래 못하던 mutate를 여기선 하지!!
3-3) toolkit: 개발툴. 설치는 1) 에서 했다~
3-4) toolkit: createSlice
- 3-2의 reducer를 이렇게!
const slice = createSlice({
name: 'reducer',
initialState,
reducers: {
setIsLoaded: (state, action) => {
state.isLoaded = action.payload;
},
},
});
const store = createStore(
slice.reducer,
composeWithDevTools(applyMiddleware()),
);
export const {setIsLoaded} = slice.actions;
그리고 actionCreators 없어졌으니 쓸 때는
import {setIsLoaded} from '../redux/store';
const mapDispatchToProps = dispatch => {
return {
setIsLoaded: (isLoaded: boolean) => dispatch(setIsLoaded(isLoaded)),
};
};
굳굳 근데 함수이름 다르게 해야겠네
4) thunk
import thunk from 'redux-thunk';
export const {setIsLoadedReducer} = slice.actions; // 아까 만들어준거
export const setIsLoadedAsync = (isLoaded: boolean) => { // 비동기 처리 위함
return async (dispatch, getState) => {
try {
dispatch(setIsLoadedReducer);
} catch (error) {
// notiE
}
};
};
-----
const mapDispatchToProps = dispatch => {
return {
setIsLoadedAsync: (isLoaded: boolean) =>
dispatch(setIsLoadedAsync(isLoaded)),
};
};
이렇게 쓰면 됩니다~ 굳굳굳굳굳
- 강의
https://academy.nomadcoders.co/courses/enrolled/235420
#1.0 Vanilla Counter
- 왜 리덕스를 쓰는지 알아야 해
- react-native 앱 생성
- count 바뀌었다고 알려주기 위해 함수 쓴다는 자체가 리덕스 쓰는 멋진 이유???????
- 다음엔 아주 심플한 리덕스로 대체할거임
#1.1~4 Store and Reducer / Actions / Subscriptions / Recap Refactor
- 설치
npm install redux
or
yarn add redux
- createStore
data를 넣을 수 있는 장소 생성.
data를 관리해주기 위해 만들어짐.
reducer를 매개변수로 받아야 함
- reducer
data를 modify하는 함수.
const reducer = () => {
return 'hello' // 이게 data가 될거야.
};
const store = createStore(reducer);
reducer 콘솔 찍어보면 이렇다
const countModifier = () => {
return 'hello'; // 이게 data가 될거야.
};
const countStore = createStore(countModifier);
console.log(countStore.getState()); // hello
어떤 함수도 count를 변경할 수 없어. reducer = data modifier만이 할 수 있다.
그 reducer는 initial state, action을 받는다.
이제 reducer에게 말하는 방법을 알아야 해.
const countModifier = (state = 0, action) => {
console.log('state action', state, action);
return state; // 이게 data가 될거야.
};
const countStore = createStore(countModifier);
countStore.dispatch({type: 'HELLO'});
그러면 콘솔로 찍은 action에는 dispatch해준 {type: 'HELLO'}가 찍힌다.
.dispatch 하면 reducer에서 액션을 찾을거야
이게 리듀서에게 메세지 보내는 방법.
reducer가 리턴하는건 모두 data가 됨!
subcribe: 변화를 알 수 있게 해줘
#2.0 Vanilla ToDo
- dd
NEVER MUTATE STATE. state는 read-only. 액션으로만 바꿀 수 있지.
상태를 수정하는 것이 아니라 새로운 object를 리턴하는거래.
not push(action.text) 그냥 새로운 object 리턴.
id: Date.now()
- actionCreatetors
#2.3 Delete To Do
- splice 대신 filter를 써라! state를 mutate하지말고 새로운 array를 반환하는 filter를~
- 나느 newArray를 만들었었는데 filter가 훨씬 간단하네?
- redux is just state. nodejs에서도 쓸 수 있어
- NEVER MUTATE STATE
#3.0 Setup
- 추가 설치
yarn add react-redux
react 에서 렌더링하기 위해 필요.
import {Provider} from 'react-redux';
import {store} from './src/store';
const App = () => {
return (
<Provider store={store}>
#3.2 mapStateToProps
- 내 컴포넌트에 store를 연결시켜줘
- store.getState() //state 가져오기 or store.dispatch() // 메세지 전달
- connect는 react와 쓰기 위해 하는거지!!! 그래서 react-redux 깔았고.
#4.1 Redux Toolkit
yarn add @reduxjs/toolkit
https://github.com/daheeahn/vanilla-redux/commit/dc5b1bc9a104590738a98d1f5915b34824f756e5
와우 코드 양 엄청 줄은거 보이지?
payload 기억하고~
#4.2 createReducer
- mutate state or return new state obj
기억하자!!!
https://github.com/daheeahn/vanilla-redux/commit/5ac7deb25bfc483bcfc33dd74ee8b2915beb1ead
#4.3 configureStore
- 함수이고 아줄 쿨한 미들웨어와 함께 store 생성
dispatcher에 payload 추가해주면 tool 안에서도 state를 추가할 수 있지
go to chart. airbnb의 state를 볼 수도 있다;;;;;;;;;;;
redux 툴 사용위해 toolkit은 필요없어
디버깅 툴 설치
middleware는 비워놓으면 됨
+ npm install -d react-devtools (이거는 뭐지? 음 필요하면 설치)
redux thunk도 적용했음
https://github.com/daheeahn/vanilla-redux/commit/a74d38d5789bdb8ae19cb5739123eacf02ccd0d1
#4.4 createSlice
- 더더욱 간결하게
https://github.com/daheeahn/vanilla-redux/commit/96bb452cf8466d7df360e9fffdb03101f9f68fb7
'Develop > React Native' 카테고리의 다른 글
[React Native] 차트 (0) | 2020.04.17 |
---|---|
[React Native] Google Login 구글 로그인 / 소셜 로그인 / 디버그용 릴리즈용 플레이스토어용 SHA-1 (0) | 2020.04.16 |
[React Native] (2021 v3 업데이트) Kakao login 카카오 로그인 구현하기 (36) | 2020.03.28 |
[React Native] 에러 모음 (2) | 2020.03.28 |
[React Native] react-navigation **v5** type checking with typescript / 타입스크립트 타입체킹 (2) | 2020.03.28 |