React-3일차

이주열·2022년 6월 28일

학습한 내용

React/ 실습 - 리액트 고급기술(컨텍스트, 리덕스)

컨텍스트

  • props는 데이터를 주고 받을 때 사용/ 매개변수 처럼 사용
  • 데이터를 주고 받을 때 간단한 구조면 props로 주고 받을 수 있지만, 주고 받아야 하는 데이터양이 많으면 쉽지 않음
  • 최상위 컨포넌트부터 최말단 컴포넌트에 걸쳐 전역 관리
  • 많은 데이터 관리하기 쉬움

접근 방법 3가지
1. consumer
2. useContext
3. contexttype

실습1

  1. 기본형으로 먼저 만들어 보기
  • 새 프로젝트 만들기
  • npx create-react-app 0628_projcontext
  • Happy hacking! 확인
  • cd 0628_projcontext : 경로 접속
  • npm start
    App.js
import React, { Component, Fragment } from 'react';
import Button from "./components/Button";
import Title from "./components/Title";
import Message from "./components/Message";

class App extends Component{
  state = {lang: "en"};

  toggleLang = () =>{
    this.setState(({lang}) => ({
      lang: lang === "en"? "kr" : "en"
    }));
  };

 render() {
   const {lang} = this.state;
  return (
    <Fragment>
     <Button lang={lang} toggleLang={this.toggleLang} />
     <Title lang={lang} />
     <Message lang={lang} />
    </Fragment>
   );
 } 
}

export default App;

Button.js

 import React from "react";

// lang이 변수, toggleLang이 함수
 function Button({lang, toggleLang}){
     return <button onClick={toggleLang}>{lang}</button>;
 }
export default Button;

Message.js

import React, {Component} from "react";

 class Message extends Component{
     render(){
         const {lang} = this.props;
         if(lang === "en")
             return(
                 <p>
                     "Context provides a way to pass data through the component tree
                     without having to pass props down manually at every level"
                 </p>
             );
         else
         return(
             <p>
                 "컨텍스트는 모든 레벨에서 이일이 props를 넘기지 않고도 컴포넌트 트리에
                 걸쳐서 데이터를 전달할 수 있는 방법을 제공합니다."
             </p>
         );
     }
 }
export default Message;

Title.js

import React from "react";

 function Title({lang}){
     const text = lang === "en"? "Context" : "컨텍스트";
     return <h1>{text}</h1>;
 }
 export default Title;

구동시킨 모습

en 버튼을 누르면 다음과 같이 변환

  1. 컨텍스트를 가지고 위 예제를 바꿔보는 실습
  • src - LangContext.js 만들기
import {createContext} from "react";

const LangContext = createContext("en");

export default LangContext;

button.js 수정

  • LangContext import 추가
  • useContext 추가
import React, { useContext } from "react";
import LangContext from "../LangContext";

function Button({toggleLang}){
    const lang = useContext(LangContext);
     return <button onClick={toggleLang}>{lang}</button>;
}

export default Button;

Title.js 수정

  • LangContext import 추가
  • LangContext.Consumer 선언
import React from "react";
import LangContext from "../LangContext";

function Title(){
    return (
        <LangContext.Consumer>
            {lang => {
                const text = lang === "en"? "Context" : "컨텍스트";
                return <h1>{text}</h1>
            }}
        </LangContext.Consumer>
    );
}

export default Title;

message.js 수정

  • LangContext import 추가
import React, {Component} from "react";
import LangContext from "../LangContext";

class Message extends Component{
    static contextType = LangContext;
    render(){
        const lang = this.context;
        if(lang === "en")
            return(
                <p>
                    "Context provides a way to pass data through the component tree
                    without having to pass props down manually at every level"
                </p>
            );
        else
        return(
            <p>
                "컨텍스트는 모든 레벨에서 이일이 props를 넘기지 않고도 컴포넌트 트리에
                걸쳐서 데이터를 전달할 수 있는 방법을 제공합니다."
            </p>
        );
    }
}

export default Message;

app.js 수정

  • Fragment 사용하지 않기에 삭제
import React, { Component } from 'react';
import Button from "./components/Button";
import Title from "./components/Title";
import Message from "./components/Message";
import LangContext from './LangContext';

class App extends Component{
  state = {lang: "en"};

  toggleLang = () =>{
    this.setState(({lang}) => ({
      lang: lang === "en"? "kr" : "en"
    }));
  };

  render() {
    const {lang} = this.state;
    return (
     <LangContext.Provider value={lang}>
      <Button toggleLang={this.toggleLang} />
      <Title/>
      <Message/>
     </LangContext.Provider>
    );
  }  
}

export default App;

실행 결과 값은 동일

실습2.
1. 기본형


import './App.css';
import React, {Component} from 'react';

// 기본형
 class AddNumber extends Component{
   render(){
     return(
       <div>
         <h1>Add Number</h1>
         <input type="button" value="+"></input>
         <input type="text" value="0"></input>
       </div>
     );
   }
 }

 class AddNumberRoot extends Component{
   render(){
     return(
       <div>
         <h1>Add Number Root</h1>
         <AddNumber></AddNumber>
       </div>
     );
  }
 }

 class DisplayNumber extends Component{
   render(){
     return(
       <div>
         <h1>Display Number</h1>
         <input type="text" value="0" readOnly></input>
       </div>
     );
   }
 }

 class DisplayNumberRoot extends Component{
   render(){
     return(
       <div>
         <h1>Display Number Root</h1>
         <DisplayNumber></DisplayNumber>
       </div>
     );
   }
 }
 function App(){
   return (
     <div className="App">
       <h1>Root</h1>
     </div>
   );
 }
export default App;
  • AddNumberRoot컴포넌트를 만듬. 이 컴포넌트는 AddNumber컴포넌트를 사용하기에 선언해준다.
  • 한 파일에다가 우리가 사용하는 컴포넌트들을 클래스 형태로 만드는 것이 예전 개발 방법
  1. 위 방법을 컴포넌트화
  • src - components 에 필요한 AddNumber.jsx, AddNumberRoot.jsx, DisplayNumber.jsx, DisplayNumberRoot.jsx 파일 생성 후 수정
    AddNumber.jsx
  • app.js에 만들었던 내용 가져오고, import 추가
import React, { Component } from "react";

class AddNumber extends Component {
  render() {
    return (
      <div>
        <h1>Add Number</h1>
        <input type="button" value="+"></input>
        <input type="text" value="0"></input>
      </div>
    );
  }
}

export default AddNumber;

AddNumberRoot.jsx

  • AddNumber과 똑같이 진행
  • AddNumber 컴포넌트를 당겨 써야 하기에 임폴트 추가
import React, {Component} from "react";
import AddNumber from "./AddNumber";

class AddNumberRoot extends Component{
    render(){
      return(
        <div>
          <h1>Add Number Root</h1>
          <AddNumber></AddNumber>
        </div>
      );
    }
  }

export default AddNumberRoot;

DisplayNumber.jsx

  • app.js에 만들었던 내용 가져오고, import 추가
import React, {Component} from "react";

class DisplayNumber extends Component{
    render(){
      return(
        <div>
          <h1>Display Number</h1>
          <input type="text" value="0" readOnly></input>
        </div>
      );
    }
  }

export default DisplayNumber;

DisplayNumberRoot.jsx

  • DisplayNumber과 똑같이 진행
  • DisplayNumber 컴포넌트를 당겨 써야 하기에 임폴트 추가
import React, {Component} from "react";
import DisplayNumber from "./DisplayNumber";

class DisplayNumberRoot extends Component{
    render(){
      return(
        <div>
          <h1>Display Number Root</h1>
          <DisplayNumber></DisplayNumber>
        </div>
      );
    }
  }

export default DisplayNumberRoot;

App.js 수정

  • 컴포넌트 사용하기 위해 import 추가해야 함
  • 컴포넌트화 한 부분 내용 삭제
  • 컴포넌트 선언
import './App.css';
import React from 'react';
import AddNumberRoot from './components/AddNumberRoot';
import DisplayNumberRoot from './components/DisplayNumberRoot';

// 컴포넌트화 
function App(){
  return (
    <div className="App">
      <h1>Root</h1>
      <AddNumberRoot></AddNumberRoot>
      <DisplayNumberRoot></DisplayNumberRoot>
    </div>
  );
}

export default App;

App.css 수정

  • div : border 추가
div{
  border : 5px solid #764abc;
  margin: 10px;
  color: #764abc;
  padding: 10px;
}

  • 다음과 같이 컴포넌트화 하기 전이랑 똑같이 나옴

학습한 내용 중 어려웠던 점 또는 해결못한 것들

해결방법 작성

실습1-1 기본형에서 구동 오류

  • import할 때 경로 설정에서 import Button from "./Button";로 하여 오류가 났었다.
  • 컴포넌트는 src 폴더 안 components안에 있으므로 app.js에 동일 위치에 있는 Button.js를 불러 오는 것이 아닌
  • 동일 위치에 있는 components 폴더 안 Button.js를 호출해야 한다.
  • import Button from "./components/Button";

학습 소감

props를 사용하지 않고 데이터를 전달하는 컨텍스트를 학습하였는데, 전역 범위에 걸쳐서 전달하는 컨텍스트가 실무에서 더 많이 사용할 것으로 예상된다. 그리고 이제 컴포넌트화 하는 방법이 익숙해지고 있지만, 하위 컴포넌트를 선언하는 과정에서 import하는 부분을 놓쳐서 오류가 자주 났다. import와 export하는 부분을 놓치지 않고 생각하는 버릇이 필요하다!

profile
예비 프론트엔드 개발자

0개의 댓글