ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • React로 블로그 만들기 #6
    2018~2019/React.js 2018. 10. 30. 14:00


    React로 블로그 만들기 #6

     - 로그인 구현(3) 로그인 상태 관리 및 ContextAPI -


    1. 로그인 상태 관리하기

    1) src/App.js

    - 앞에서 소셜 로그인을 구현하여 로그인해서 정보를 받아옴.

    - 로그인 상태를 관리하기 위해 logged를 state에 생성한다.

    - 로그인을 하면 logged를 true로 바꿔줄 onLogin 함수와 로그아웃을 하면 logged를 false로 바꿔줄 onLogout 함수를 만든다.

    import React, { Component } from 'react';
    import styled from 'styled-components';
    import Header from './Layout/Header';
    import Navigation from './Layout/Navigation';
    import Router from './Routes/Router';
    import Store from './Store/store';

    class App extends Component {

    constructor(props) {
    super(props)
    this.state = {
    logged: false,
    onLogin: this.onLogin,
    onLogout: this.onLogout
    }
    }

    // Login Func
    onLogin = () => {
    this.setState({
    logged: true
    });
    }

    // Logout Func
    onLogout = () => {
    this.setState({
    logged: false
    });
    }
    render() {
    const { logged, onLogout } = this.state;

    return (
    <Layout>
    <Header logged={logged} onLogout={onLogout}/>
    <Navigation />
    <Content>
    <Router />
    </Content>
    </Layout>
    );
    }
    }

    export default App;


    2) src/Layout/Header.js

    - 부모컴포넌트(App)에서 받아온 logged, onLogout을 통해 로그인 전에는 '로그인/회원가입'을 로그인 후에는 '로그아웃'으로 글씨 변경

    - 로그아웃일 경우 onLogout함수를 통해 logged를 다시 false로 바꿔준다.

    import React, { Component } from 'react';
    import styled from 'styled-components';
    import { Link } from 'react-router-dom';

    class Header extends Component {

    render() {
    const { logged, onLogout } = this.props;

    return (
    <Container>
    <Element>
    {logged ?
    <ShortCut><Link to="/" onClick={onLogout}>로그아웃</Link></ShortCut> :
    <ShortCut><Link to="/login">로그인/회원가입</Link></ShortCut>}
    <Logo>
    <img
    width="100%"
    height="100%"
    src="https://t1.daumcdn.net/cfile/tistory/99CD014B5BD01FA412"
    alt="logo"/>
    </Logo>
    <Search>
    <Link to="/" style={{textDecoration: 'none', color:'#274046'}}>
    <h1>React Blog</h1>
    </Link>
    </Search>
    </Element>
    </Container>
    );
    }
    }
    export default Header;


    - Header컴포넌트의 경우 부모컴포넌트가 바로 App이므로 props를 통해 value를 전달 받을 수 있다. 그러나 Login컴포넌트의 경우는 여러 번 전달 해야 함. 따라서 전역적인 상태가 필요하다.


    2. ContextAPI

    - 어플리케이션에서 전역으로 상태를 관리하기 위한 라이브러리

    - 리액트에서 상태 관리 라이브러리에는 대표적으로 Redux가 있음. 리덕스는 상태 관리 외에도 많은 장점이 있음. 그러나 지금 블로그 앱에서 단순한 상태 관리를 위해서 리덕스를 사용하기에는 코드가 방대하지고 복잡해므로 Context API를 사용함.

    - 유저가 로그인했는 지 안했는 지 전역으로 로그인 상태를 관리함


    1) src/Store/store.js 생성

    - context를 만들어준다

    import React from 'react';
    const Store = React.createContext();

    export default Store;


    2) src/App.js

    - 위에서 만든 스토어를 import한다.

    - Store.Provider에 전역으로 관리할 state(logged, onLogin, onLogout)를 넣어준다.

    import React, { Component } from 'react';
    import styled from 'styled-components';
    import Header from './Layout/Header';
    import Navigation from './Layout/Navigation';
    import Router from './Routes/Router';
    import Store from './Store/store';

    class App extends Component {

    constructor(props) {
    super(props)
    this.state = {
    logged: false,
    onLogin: this.onLogin,
    onLogout: this.onLogout
    }
    }

    // Login Func
    onLogin = () => {
    this.setState({
    logged: true
    });
    }

    // Logout Func
    onLogout = () => {
    this.setState({
    logged: false
    });
    }
    render() {
    const { logged, onLogout } = this.state;

    return (
    <Store.Provider value={this.state}>
    <Layout>
    <Header logged={logged} onLogout={onLogout}/>
    <Navigation />
    <Content>
    <Router />
    </Content>
    </Layout>
    </Store.Provider>
    );
    }
    }

    const Layout = styled.div`
    margin: 0 auto;
    display: flex;
    width: 100%;
    flex-flow: row wrap;
    `
    const Content = styled.div`
    margin: 0 auto;
    `

    export default App;


    3) src/Components/LoginContainer.js 생성

    - Store에 저장된 value를 사용하기 위해 Store.Consumer를 받을 컨테이너 컴포넌트 생성

    - Login 컴포넌트에 Store에 저장된 onLogin함수를 넣어준다.

    import React, { Component } from 'react';
    import Store from '../Store/store';
    import Login from './Login';

    const LoginContainer = () => (
    <Store.Consumer>
    {store => (
    <Login onLogin={store.onLogin}/>)}
    </Store.Consumer>
    )
    export default LoginContainer;


    4) src/Components/Login.js

    로그인에 성공한 경우, LoginContainer를 통해 전달받은 onLogin함수를 실행한다. => this.props.onLogin();

    - 또 홈 화면으로 이동하기 위해 withRouter를 이용하여 Login을 감싸준다. => this.props.history.push('/');

    import React, { Component } from 'react';
    import { GoogleLogin } from 'react-google-login';
    import KakaoLogin from 'react-kakao-login';
    import styled from 'styled-components';
    import { withRouter } from "react-router-dom";

    class Login extends Component {

    constructor(props) {
    super(props);
    this.state = {
    id: '',
    name: '',
    provider: '',
    }
    }
    // Google Login
    responseGoogle = (res) => {
    this.setState({
    id: res.googleId,
    name: res.profileObj.name,
    provider: 'google'
    });
    this.props.onLogin();
    this.props.history.push('/');
    }
    // Kakao Login
    responseKakao = (res) => {
    this.setState({
    id: res.profile.id,
    name: res.profile.properties.nickname,
    provider: 'kakao'
    });
    this.props.onLogin();
    this.props.history.push('/');
    }

    // Login Fail
    responseFail = (err) => {
    console.error(err);
    }

    render() {
    return (
    <Container>
    <GoogleLogin
    clientId={process.env.REACT_APP_Google}
    buttonText="Google"
    onSuccess={this.responseGoogle}
    onFailure={this.responseFail}
    />
    <KakaoButton
    jsKey={process.env.REACT_APP_Kakao}
    buttonText="Kakao"
    onSuccess={this.responseKakao}
    onFailure={this.responseFail}
    getProfile="true"
    />
    </Container>
    );
    }
    }

    export default withRouter(Login);


    5) src/Routes/index.js

    - Login컴포넌트를 LoginContainer 컴포넌트로 변경한다.

    export { default as Home } from '../Components/Home';
    export { default as Login } from '../Components/LoginContainer';
    export { default as About } from '../Components/About';
    export { default as Board } from '../Components/Board';
    export { default as MyBoard } from '../Components/MyBoard';
    export { default as MyPage } from '../Components/MyPage';


    6) 결과

    - logged가 false인 경우

    - logged가 true인 경우


    '2018~2019 > React.js' 카테고리의 다른 글

    React로 블로그 만들기 #8  (2) 2018.11.04
    React로 블로그 만들기 #7  (0) 2018.11.01
    React로 블로그 만들기 #5  (3) 2018.10.29
    React로 블로그 만들기 #4  (1) 2018.10.26
    React로 블로그 만들기 #3  (0) 2018.10.26
Designed by Tistory.