만족
[React] MobX 실제로 사용해보기 본문
[React] MobX 실제로 사용해보기
FrontEnd/React Satisfaction 2020. 10. 10. 03:38satisfactoryplace.tistory.com/154?category=829221
위 포스트에서 이어지는 내용이다.
이번엔 MobX로 실제로 어떤 것을 해볼 수 있는지를 살펴보자.
우선 observerable state의 위치에 따른(내부/외부) state사용법에 대해 알아볼 것이다.
class Timer {
secondsPassed = 0
constructor() {
makeAutoObservable(this)
}
increaseTimer() {
this.secondsPassed += 1
}
}
const myTimer = new Timer()
위의 Observable한 state인 myTimer를 가지고 설명할 것이다.
외부 상태를 사용하는 컴포넌트
props를 사용하는 경우
const TimerView = observer(({ timer }) => <span>Seconds passed: {timer.secondsPassed}</span>)
// Pass myTimer as a prop.
ReactDOM.render(<TimerView timer={myTimer} />, document.body)
myTimer를 props로 전달하고, 이를 받는 컴포넌트는 observer()를 이용해 컴포넌트를 래핑되어 myTimer의 상태 변화에 따라 사이드이펙트가 발생한다.
전역변수를 사용하는 경우
// No props, `myTimer` is directly consumed from the closure.
const TimerView = observer(() => <span>Seconds passed: {myTimer.secondsPassed}</span>)
ReactDOM.render(<TimerView />, document.body)
observer로 래핑된 컴포넌트 내에서 myTimer의 상태 변화에 따라 사이드이펙트가 발생한다.
React Context를 사용하는 경우
const TimerView = observer(() => {
// Grab the timer from the context.
const timer = useContext(TimerContext) // See the Timer definition above.
return (
<span>Seconds passed: {timer.secondsPassed}</span>
)
})
ReactDOM.render(
<TimerContext.Provider value={new Timer()}
<TimerView />
</TimerContext.Provider>,
document.body
)
컨텍스트에 상태값을 넣고 Provider 하위의 observer로 래핑된 컴포넌트에서 useContext를 이용해
observable state를 가져와 해당 상태 변화에 따라 사이드이펙트가 발생한다.
내부 상태를 사용하는 컴포넌트
이 항목은 따로 설명하지 않을 것이다.
필요한 경우 아래 링크를 참조할 것.
mobx.js.org/react-integration.html
예시- 로그인 상태 관리
간단한 예제를 위해 id/pw를 직접 저장했으나, 실제로는 그렇게 해서는 안되고
token을 저장하거나 하는 방식으로 인증을 처리한다는 점을 알아두길 바란다.
auth.js (observable)
class Auth{
constructor(){
makeAutoObservable();
}
id= '';
pw= '';
login(){
id= 'testId';
pw= 'myPassword';
}
logout(){
id='';
pw='';
}
}
const auth= new Auth();
export default auth;
Auth.js (observer component)
const Auth= ()=>{
return <div>
아이디: {auth.id}
<br/>
비밀번호: {auth.pw}
<br/><br/>
<span onClick={e=> auth.login()}>로그인</span>
<span onClick={e=> auth.logout()}></span>
</div>
};
export default observer(Auth);
이렇게 하면 auth.js에서 export한 auth state를 observer로 감싸진 모든 컴포넌트 내에서 전역적으로 쓸 수 있게 된다.
가령 AuthState.js (observer component) 파일이 다음과 같이 생겼다고 하면,
const AuthState= ()=>{
return <p>
{auth.id && auth.pw? '로그인 되었습니다': '로그인되지 않았습니다'}
</p>
};
export default observer(AuthState);
위와 같이 사용할 수도 있다.
주의: props로 전달할 때
만약 Auth.js와 AuthState.js가 다음과 같이 생겼다고 해보자.
const Auth= ()=>{
return <div>
<AuthState auth={auth}/>
<br/><br/>
<span onClick={e=> auth.login()}>로그인</span>
<span onClick={e=> auth.logout()}></span>
</div>
};
export default observer(Auth);
const AuthState= ({auth})=>{
return <p>
{auth.id && auth.pw? '로그인 되었습니다': '로그인되지 않았습니다'}
</p>
};
//더 이상 observer()로 감싸지 않는다
export default AuthState;
AuthState는 login()/logout()에 따라 정상적으로 작동하지 않을 수 있다.
왜냐하면 auth는 observable state임에도 AuthState는 observer()로 래핑되지 않았기 때문이다.
이에 대한 해법은 다음과 같다.
const Auth= ()=>{
return <div>
<AuthState auth={{id: auth.id, pw: auth.pw}}/>
<br/><br/>
<span onClick={e=> auth.login()}>로그인</span>
<span onClick={e=> auth.logout()}></span>
</div>
};
export default observer(Auth);
AuthState에 props를 전달할 때 auth를 뜯어서 새로운 object를 만들어서 전달하는 방법이 있고
const Auth= ()=>{
return <div>
<AuthState auth={toJS(auth)}/>
<br/><br/>
<span onClick={e=> auth.login()}>로그인</span>
<span onClick={e=> auth.logout()}></span>
</div>
};
export default observer(Auth);
toJS를 이용해 객체를 역직렬화해 전달하는 방법도 있다.
주의: 콜백 형태로 렌더할 때
Renderer.js
const Renderer= ({onRender})=>{
return onRender();
};
export default Renderer;
Auth.js
const Auth= ()=>{
return <div>
<Renderer onRender={()=> <p>아이디: {auth.id}</p>}/>
<Renderer onRender={()=> <p>비밀번호: {auth.pw}</p>}/>
<br/><br/>
<span onClick={e=> auth.login()}>로그인</span>
<span onClick={e=> auth.logout()}></span>
</div>
};
export default observer(Auth);
다음과 같은 컴포넌트가 있다고 해 보자.
이 경우에도 Renderer와 렌더링 될 컴포넌트가 observer가 아니기 때문에 정상적으로 작동하지 않는다.
이럴 때는 <Observer></Observer>로 감싼 뒤, 렌더링할 내용을 다시 한번 콜백으로 만든다.
const Auth= ()=>{
return <div>
<Renderer onRender={()=> <Observer>{()=><p>아이디: {auth.id}</p>}</Observer>}/>
<Renderer onRender={()=> <Observer>{()=><p>비밀번호: {auth.pw}</p>}</Observer>}/>
<br/><br/>
<span onClick={e=> auth.login()}>로그인</span>
<span onClick={e=> auth.logout()}></span>
</div>
};
export default observer(Auth);
이제 정상작동한다.
그 외
http.js
export const getUserInfo= ()=>{
const token= auth.token;
return axios.get('https://test.com', {headers: {Authorization: 'Bearer '+ token}});
};
위와 같이 http.js파일에서 요구하는 인증 헤더값을 함수 파라미터가 아닌
global observerable state로부터 불러와서 사용할 수도 있다.
여러모로 편리한 점이 많으니 한번쯤 사용해보는것을 추천한다.
'FrontEnd > React' 카테고리의 다른 글
[React] Hook과 함께 HOC 사용해보기 (1) | 2020.11.04 |
---|---|
[React] 404 페이지 만들기 (0) | 2020.10.20 |
[React] MobX 개요 (0) | 2020.10.04 |
[React] 애드센스 합격 과정 (22) | 2020.09.14 |
[React] 페이지별 메타 태그 추가 (2) | 2020.09.14 |