React Native로 코드를 작성하던 중 문제에 부딪혔다.
기존에는 State를 따로 관리할 필요가 없었지만 컴포넌트들이 많아질수록 구조가 Nested해졌고
계속 props로 넘겨주기엔 너무 귀찮았다.
그러다가 Redux라는걸 발견했고 사용해보기로 했다.
다 좋았는데 문제가 발생했다.
connect해준 값을 export해주면 connect해준 컴포넌트에만 State가 전달됐다.
나는 모든 컴포넌트에 State를 전달해주고 싶었지만 그렇게 동작하지 않았다.
react redux multiple components
redux connect every components
등 수많은 검색어를 입력하고 찾아봤지만 방법을 찾지 못했다.
튼 각설하고 구조부터 살펴보자면 다음과 같다.
App.js -> LoginRouter.js -> Mypage.js -> Main.js
하나하나 소스부터 보자.
[App.js]
[LoginRouter.js]
[Mypage.js]
[Main.js]
최대한 쉽게 설명하기 위해 코드를 간단하게 작성했다.
보면 알겠지만 별거없고 Mypage.js에서 Main.js를 렌더링한다.
먼저 LoginRouter.js에서 아래와 같은 코드로 export 해봤다.
export default connect(mapStateToProps)(Mypage);
이러면 Mypage에는 State가 전달되지만 하위 컴포넌트인 Main.js에는 전달되지 않는다.
다음으로 아래와 같이 작성해봤다.
export default connect(mapStateToProps)(Main);
이렇게 작성하면 Main.js에는 작성하지만 상위 컴포넌트인 Mypage.js에는 전달되지 않는다.
어떻게 할까 생각해봤다.
나는 connect에 여러개의 값을 한번에 줘서 export하는게 가장 좋을 방법이라고 생각했다.
하나의 파일에서 관리해주는게 가장 쉬우니까?
근데 방법을 찾지 못했다.
방법이 있을 것 같은데, 구글링해서 나온 map을 이용한 전달도 제대로 동작하지 않았다.
튼 다른 방법으로 해결했는데 바로 각 컴포넌트에서 connect후 export를 하는 것이다.
생각해보면 당연한 방법인데 아직 리액트의 구조에 대해 정확하게 파악하지 못해서 생긴 문제점 같다.
따라서 위의 코드에서 변경된점만 적어보자면
LoginRouter.js 에서
export default connect(mapStateToProps)(Mypage);
로 export하고
Mypage.js도 마찬가지로
export default connect(mapStateToProps)(Mypage);
Main.js도
export default connect(mapStateToProps)(Main);
로 connect 후 export 해주면 문제가 쉽게 해결된다.
Mypage.js와 Main.js에서 전달받은 State를 찍어보면 다음과 같다.
아래는 풀 소스
[App.js]
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducer';
import LoginRouter from './LoginRouter';
let store = createStore(reducer);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<LoginRouter />
</Provider>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Mypage from './Mypage';
import Main from './Main';
import { connect } from 'react-redux';
import mapStateToProps from './mapStateToProps';
export default connect(mapStateToProps)(Mypage);
[Mypage.js]
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Main from './Main.js';
import mapStateToProps from './mapStateToProps';
import { connect } from 'react-redux';
class Mypage extends Component {
render() {
console.log("Mypage => ");
console.log(this.props);
const { isLogin } = this.props;
return (
<View style={styles.container}>
<Text>Mypage</Text>
<Main />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})
export default connect(mapStateToProps)(Mypage);
[reducer.js]
const USER_LOGIN = 'USER_LOGIN';
const USER_LOGOUT = 'USER_LOGOUT';
function userLogin() {
return {
type: USER_LOGIN
};
}
function userLogout() {
return {
type: USER_LOGOUT
};
}
const initialState = {
isLogin: false
}
function reducer(state = initialState, action) {
switch(action.type) {
case USER_LOGIN:
return applyUserLogin(state);
case USER_LOGOUT:
return applyUserLogout(state);
default:
return state;
}
}
function applyUserLogin(state, action) {
return {
...state,
isLogin: true
}
}
function applyUserLogout(state, action) {
return {
...state,
isLogin: false
}
}
const actionCreators = {
userLogin,
userLogout
};
export { actionCreators }
export default reducer;
[mapStateToProps.js]
function mapStateToProps(state) {
const { isLogin} = state;
return {
isLogin
}
}
export default mapStateToProps;
[Main.js]
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import mapStateToProps from './mapStateToProps';
import { connect } from 'react-redux';
class Main extends Component {
render() {
console.log("Main => ");
console.log(this.props);
return (
<View>
<Text>Main</Text>
</View>
);
}
}
export default connect(mapStateToProps)(Main);
Reference : https://gist.github.com/StlthyLee/02e116d945867a77c382fa0105af1bf3
'Coding > Etc' 카테고리의 다른 글
The virtual environment was not created successfully because ensurepip is not available. 오류해결 (0) | 2018.02.02 |
---|---|
HTML5 deatils태그 onToggle 속성 (0) | 2018.01.31 |
[React.js] 구글 Firebase 연동하는 방법 (0) | 2018.01.27 |
[React.js] react-native-elements 설치하는 방법 (0) | 2018.01.26 |
[React.js] Halogen으로 Loading Indicator 만들기 (0) | 2018.01.26 |