Redux 시작하기
파일 구조 및 기본 세팅
정석으로는 어떻게 하는지 모르겠지만 나는 src 폴더 하위에 redux 폴더를 만들었다. 이 폴더 안에 여러 state들을 각 파일로 만들어두고, index.js로 관리한다.
index.js에서 redux로 관리할 전역 상태값들을 연결시켜준다. 루트 리듀서를 디폴트로 export 한다.
// src.redux.index.js
import {combineReducers} from 'redux';
import token from './token';
const rootReducer = combineReducers({
token,
});
export default rootReducer;
모든 화면을 navigating하는 App.js에서 store를 주입한다. createStore로 redux state들이 저장되는 store를 만들고, Provider 컴포넌트로 모든 요소들을 감싼 후 거기에 store를 props로 전달하면 된다.
import React from 'react';
import {createStore} from 'redux';
import {Provider} from 'react-redux';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import Login from './src/screens/Login';
import rootReducer from './src/redux';
const store = createStore(rootReducer);
const Stack = createNativeStackNavigator();
const App = () => {
return (
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator initialRouteName="Login">
<Stack.Screen
name="Login"
component={Login}
options={{headerShown: false}}></Stack.Screen>
</NavigationContainer>
</Provider>
);
};
export default App;
reducer 예시
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
state 값을 변경시키는 동작을 하는 함수. switch문을 이용해서 action에 따라 다른 동작을 취한다.
https://ko.redux.js.org/usage/structuring-reducers/basic-reducer-structure
action과 reducer
const initialState = {token: ''};
// Action Type
const SET = 'token/SET';
const REMOVE = 'token/REMOVE';
// Action Creator & Action
export const set = newToken => ({type: SET, access: newToken});
export const remove = () => ({type: REMOVE});
// Reducer
export default function token(state = initialState, action) {
switch (action.type) {
case SET:
return {access: action.access};
case REMOVE:
return initialState;
default:
return state;
}
}
참고
- [React/ReactNative] Redux 사용하기 https://133hyun.tistory.com/59
- React-Redux 핵심 요약본 https://velog.io/@jeffyoun/React-Redux-%ED%95%B5%EC%8B%AC-%EC%9A%94%EC%95%BD%EB%B3%B8
- https://juhi.tistory.com/23
- https://blog.woolta.com/categories/1/posts/200
- 리덕스 개념 및 구조 => https://devbirdfeet.tistory.com/183
계좌번호 형식 검증
숫자로만 입력 받았다고 가정하고 입력 완료 후 백엔드에 전송할 때 수정하기
const isActive = accountInput.length === accountLength && bankCode;
const modifyAccount = () => {
if (!bankCode) {
return;
}
const {validation} = bankData[bankCode];
let accountArr = accountInput.split('');
for (let i = 0; i < validation.index.length; i++) {
accountArr.splice(validation.index[i], 0, '-');
}
return accountArr.join('');
};
const checkAccount = () => {
if (!isActive) {
return;
}
const accountNumber = modifyAccount();
const regex = new RegExp(bankData[bankCode].validation.regex);
const isValid = regex.test(accountNumber);
if (!isValid) {
// 모달 띄우기
console.log('여기는 프론트, 오류 모달창 뜰 거임');
return;
}
fetch(API.account, {
method: 'POST',
headers: {
Authorization: `Bearer ${token.access}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
bank: bank.slice(0, 2),
account_number: '123456-12-123456',
}),
})
.then(res => res.json())
.then(result => {
console.log(result);
if (result.length) {
AsyncStorage.setItem('recipient', result[1]);
alert('계좌조회 성공');
} else if (
result.non_field_errors[0] === '계좌번호가 존재하지 않습니다.'
) {
// 모달 띄우기
console.log('여기는 백, 오류 모달창 뜰 거임');
}
});
};
-(hyphen) 빼고 숫자만 전송하고 저장하기
실제로 계좌번호를 검증할 때, 계좌번호의 길이와 형식이 은행마다, 은행에서도 휴대폰번호를 계좌번호를 쓰냐 등에 따라 달라지기 때문에 hyphen을 삽입하는 것이 의미가 없다고 한다. 게다가 계좌번호를 비교할 데이터베이스에서도 숫자만으로 이뤄진 계좌번호로 저장되어있기 때문에, 오히려 hyphen이 포함되었을 경우 제거하고 숫자만 보내야 한다고 한다.
1. replace 메서드 이용
const isActive = accountInput.length > 0 && bank !== '은행을 선택하세요.';
const modifyAccount = () => {
if (accountInput.includes('-')) {
return accountInput.replace('-', '');
} else {
return accountInput;
}
};
const checkAccount = () => {
if (!isActive) {
return;
}
const accountNumber = modifyAccount();
fetch(API.account, {
method: 'POST',
headers: {
Authorization: `Bearer ${token.access}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
bank: bank.slice(0, 2),
account_number: accountNumber,
}),
})
.then(res => res.json())
.then(result => {
console.log(result);
if (result.length) {
AsyncStorage.setItem('recipient', result[1]);
alert('계좌조회 성공');
} else if (
result.non_field_errors[0] === '계좌번호가 존재하지 않습니다.'
) {
// 모달 띄우기
console.log('여기는 백, 오류 모달창 뜰 거임');
}
});
};
replace() 메서드를 사용하여 "-"를 모두 ""로 바꾸어 없앴다. 그런데 "-" 외에 "." 같은 다른 기호도 잘못 입력될 수 있으니, 정규표현식으로 숫자가 아닌 모든 문자열을 ""로 바꾸는 방법도 있다.
// 출처 : https://stackoverflow.com/questions/32946793/react-native-textinput-that-only-accepts-numeric-characters
text.replace(/[^0-9]/g, '')
이 방법이 더 완전해보인다.
- JavaScript의 문자열에서 부분 문자열 제거 https://www.delftstack.com/ko/howto/javascript/javascript-remove-substring-from-string/#%EB%AC%B8%EC%9E%90%EC%97%B4%EC%97%90%EC%84%9C-%ED%8A%B9%EC%A0%95-%ED%95%98%EC%9C%84-%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84-%EC%A0%9C%EA%B1%B0%ED%95%98%EB%8A%94-javascript-replace-%EB%A9%94%EC%84%9C%EB%93%9C
- https://stackoverflow.com/questions/32946793/react-native-textinput-that-only-accepts-numeric-characters
- JS 정규식 정리(숫자만, 한글만, 메일, 전화번호, 비밀번호) https://passionha.tistory.com/382
- https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions
2. TextInput에서 숫자만 입력받기
위의 정규식을 사용하여 아예 input에 값을 입력할 때부터 수정할 수 있다.
<TextInput
style={styles.accountInput}
keyboardType="number-pad"
editable={bank !== '은행을 선택하세요.'}
placeholder="계좌번호를 입력하세요."
value={accountInput}
onChangeText={text => {
setAccountInput(text.replace(/[^0-9]/, ''));
}}
maxLength={20}
/>
이게 훨씬 깔끔한 것 같다. modifyAccount() 함수를 따로 이용할 필요도 없다.
에러: 삼항 조건 연산자 적용 안됨
변수 선언 순서
const borderColor = isActive ? 'rgb(156, 123, 252)' : 'rgb(235, 235, 235)';
const isActive = accountInput.length > 0 && bank !== '은행을 선택하세요.';
borderColor를 활성화 여부에 따라 다르게 적용하고 싶어서 삼항 조건 연산자로 색깔을 변수로 만들어두었다. 그런데 isActive가 true일 때도 항상 rgb(235, 235, 235)가 나와서 이상했다.
함수에서는 아래에 선언한 함수를 위에서 사용해도 괜찮아서 문제가 없는 줄 알았다. (호이스팅 때문??) 그런데 변수에서는 그렇지 않은가보다. 기본적인 걸 잊고 있었다. 변수가 선언되기 전에 사용해서 isActive는 항상 없는 값이었던 듯. isActive 선언부를 위로 올리니까 잘 작동한다!
'TIL' 카테고리의 다른 글
[TIL-163] React Native (0) | 2022.04.11 |
---|---|
[TIL-162] 노마드코더 React Native #2.0~# (0) | 2022.04.09 |
[TIL-160] React Native (0) | 2022.04.07 |
[TIL-159] React Native (0) | 2022.04.06 |
[TIL-158] React Native (0) | 2022.04.04 |