mjeongriver
article thumbnail
Published 2023. 1. 25. 17:18
day72-react TIL/React

1, 리액트 contextAPI

1) 데이터를 전역으로 관리하자 contextAPI or Redux

- API 문서 : https://ko.reactjs.org/docs/context.html

 

Context – React

A JavaScript library for building user interfaces

ko.reactjs.org

- React를 하다보면 여러 컴포넌트를 거쳐서 자료를 전달해야 하거나, 동시에 같은 자료를 사용해야 하는 경우가 생깁니다.

  • Context는 리액트 컴포넌트 간에 어떠한 값을 공유 할 수 있게 해주는 기능입니다.
  • 주로 Context는 전역적(global)으로 필요한 값을 다룰 때 사용합니다.

 

2) Props로만 데이터를 전달하는 것은 한계가 있다.

- 리액트에서는 일반적으로 컴포넌트에게 데이터를 전달해 주어야 할 때 Props를 통해 전달합니다.

- 그런데, 이 컴포넌트의 형태가 복잡하다면 어떻게 될까요?

https://velopert.com/3606

- G에서 변경된 값을 J로 가져가려면 Root를 거쳐 J로 돌아가야 합니다.

- G값을 핸들링하는 함수 또한 Root에서 선언 해야합니다.

- Props를 통해 핸들링 함수를 자식 컴포넌트(JS는 변수로 함수를 전달 가능) 로 전달해줘야 합니다.

- 이런 문제는 Context API 또는 Redux를 사용하여 공통(전역)으로 사용하는 데이터를 외부에서 편리하게 사용할 수 있습니다.

 

 

3) contextAPI 사용 방법(생성과 사용이 나눠짐)

- createContext() 훅 : ContextAPI를 생성합니다.

const 사용할이름 = createContext(초기값)

 

- provider(제공자: 루트가 되는 부모 컴포넌트)와 consumer(소비자: 사용하는 측, 사용하고 싶은 자식 컴포넌트)

 

Provider Component 부모에서 사용 Context의 변화를 하위 컴포넌트에 알린다.
Consumer Component 자식에서 사용 부모 Component중 가장 가까운 Provider가 전달하는 데이터를 받아서 사용한다.

 

- 구현순서(2, 3은 순서 바뀌어도 무관)

1) ContextAPI를 생성한다.

2) 자식 컴포넌트에서는 Consumer를 이용해서 데이터 받기

3) 부모 컴포넌트에서는 Provider를 사용해서 value값을 제어한다.

 

- ContextAPI.js 생성

import { createContext } from "react";

//컨텍스트의 기본상태 지정
const ColorContext = createContext({color : 'red'}) //초기값 설정

export default ColorContext; //외부에서 사용하도록 export

- ColorComponent.js 안에서 Consumer의 사용

  • Context 변화를 사용하는 React 컴포넌트입니다. 이 컴포넌트를 사용하면 함수 컴포넌트안에서 Context를 사용 할 수 있습니다.
  • Context.Consumer의 자식은 함수여야합니다. (첫번째 매개변수에서 context값을 얻습니다)
  • return에 화면에 렌더링할 JSX를 만듭니다.
//...
const ColorComponent = () => {

    return (
        <ColorContext.Consumer>
            {/* ColorContext 안에 Consumer를 사용하고 
            JSX자리에 함수로 return을 처리하는 구문을 사용함 */}
            {
                (value) => (
                    <div style={{background: value.color}}> 
                        ConTextAPI사용<br/>
                        값: {value.color}
                    </div>
                )
            }
        </ColorContext.Consumer>

    )

}

export default ColorComponent;

- App.js 안에서 Provider의 사용

  • Context에 포함된 React 컴포넌트인 Provider는 context를 사용하는 컴포넌트들에게 context의 변화를 알리는 역할을 합니다.
  • Provider 컴포넌트는 value prop을 받아서 이 값을 하위에 있는 컴포넌트에게 전달합니다.
  • Provider 하위에서 context를 사용하는 모든 컴포넌트는 Provider의 value prop가 바뀔 때마다 다시 렌더링 됩니다.
//...
const App = () => {

    return (
        <ColorContext.Provider value={{color: 'green'}}>
            <ColorComponent/>
        </ColorContext.Provider>

    )
}

export default App;

 

* 예제 - app.js, contextAPI.js, ColorComponent.js

import { Fragment, useState, handleChange } from "react";
import ColorComponent from "./component3/ColorComponent";
import ColorContext from "./contexts/ContextAPI";

const App = () => {

    /* 
    p. 495
    1. ContextAPI를 외부에 선언 createContext() 훅 사용
    2. 자식 컴포넌트 consumer로 데이터를 받기
    3. 부모 컴포넌트 provider로 데이터를 전달
     */

    //select 태그를 만들고 usestate를 활용해서 color값을 변경
    /*  const [color, setColor] = useState('black'); */
    const [color, setColor] = useState('black');
    const handleChange = (e) => {
        setColor(e.target.value);
    }

    return (
        <ColorContext.Provider value={{ color: color }}>
            {/* Provider는 사용할 root컴포넌트에 선언합니다. */}
            <ColorComponent />

            {/*  내 답안
           <select onChange={(e) => {
                setColor(e.target.value);
            }}>
                <option>red</option>
                <option>blue</option>
                <option>orange</option>
            </select> 
            */}

            <select onChange={handleChange}>
                <option value='black'>선택</option>
                <option value='blue'>blue</option>
                <option value='red'>red</option>
            </select>


        </ColorContext.Provider>

    )
}

export default App;
import { createContext } from "react";

//컨텍스트의 기본 상태 지정
const ColorContext = createContext({color: 'red'});

export default ColorContext;
import { Fragment } from "react";
import ColorContext from "../contexts/ContextAPI";


const ColorComponent = () => {

    return (
            <ColorContext.Consumer>
            {/* 사용할 곳: Consumer - 함수의 return구문에 화면을 처리할 내용을 작성함 */}
                {
                    (value) => ( /* 소괄호, value-contextAPI에서 관리하는 초기값을 넣어줌 */
                        <div style={{color: value.color}}>
                            ContextAPI의 사용
                            값: {value.color}
                        </div>
                    )
                }
            </ColorContext.Consumer>
    )
}

export default ColorComponent;

 

4) Provider와 consumer를 독립적으로 분리하기

  • ContextAPI는 전역으로 사용할 값이기 때문에 파일을 독립적으로 분리해서 작성하도록 변경합니다.
  • 하위 컴포넌트에서는 훅을 이용해서 더욱 편리하게 사용할 수 있습니다.

 

- useContext() 훅

  • 컴포넌트에서 context API를 편하게 사용하는 훅입니다
  • 리턴은 객체이고 첫번째 값은 상태값, 두번째는 값을 저장하는 setter를 가진 객체를 반환합니다.
const {state, action} = useContext(컨택스트API객체)

 

- 구현순서

  1. ContextAPI2.js 생성 (Provider재정의, Consumer를 외부로 export)
  2. App.js에서 Provider감싸기
  3. A.js 훅 으로 컨텍스트 사용하기

- ContextAPI2.js 에서는...

import { createContext, useState } from "react";


//1. 초기값 설정
const UserContext = createContext({
    state : {id: 'aaa', name : 'bbb'},
    action : {
        setUser : () => {}
    }
});

//2. Provider컴포넌트 재정의
//매개값의 이름은 반드시 children으로 구조분해할당 합니다.
//useState를 활용해서 데이터를 관리합니다.
const UserProvider = ({children}) => {
    const [user, setUser] = useState({id: 'aaa', name: 'bbb'});
    const value = {
        state : user,
        action : {setUser}
    }
    //Provider 반환
    return (
        <UserContext.Provider value={value}>{children}</UserContext.Provider>
    )
}

//3. 외부에서 사용가능 하도록 consumer, provider 반환
const UserConsumer = UserContext.Consumer;
export {UserProvider, UserConsumer}

export default UserContext;

- App.js에서는

import A from "./component3/A";
import B from "./component3/B";
import { UserProvider } from "./contexts/ContextAPI2";

const App = () => {

    return (
        <UserProvider>
            <A/>
            <B/>
        </UserProvider>

    )
}

export default App;

- A.js 그리고 B.js에서는

import { useContext, useRef } from "react";
import UserContext, { UserConsumer } from "../contexts/ContextAPI2";

const A = () => {
    //useRef훅
    const input1 = useRef(null);
    const input2 = useRef(null);

    //useContext훅 - 을 이용해서 값 조회 or 값 변경
    //Context API를 훅으로 사용
    const {state, action} = useContext(UserContext);

    const handleClick = () => {
        action.setUser({id: input1.current.value,
                       name: input2.current.value});
        
        input1.current.value = '';               
        input2.current.value = '';               
    }

    return (
        <div>
            <h3>A컴포넌트</h3>
            <input type="text" ref={input1}/>
            <input type="text" ref={input2}/>
            <button onClick={handleClick}>데이터변경</button>

            <div>
                {state.id}<br/>
                {state.name}<br/>
            </div>

        </div>
    )
}

export default A;

 

* 예제 - App.js, contextAPI2, A~D.js

import A from "./component3/A"
import B from "./component3/B"
import { UserProvider } from "./contexts/ContextAPI2";

const App = () => {

    /*
    전역 데이터 관리 ContextAPI
    
    1. 외부 contextAPI2의 컨슈머, 프로바이더 export
    2. root에서는 export된 프로바이더로 감싸줍니다.
    3. 사용하는 곳에서는 useContext 훅을 사용 - 자식 컴포넌트에서는 useContext(컨텍스트명)를 이용해서 데이터를 핸들링
     */

    return (
        <UserProvider>
        <A/>
        <B/>
        </UserProvider> /* return에 <UserContext.Provider value = {value}>{children}</UserContext.Provider> */
    )
}

export default App;
import { createContext, useState } from "react";


//1. 초기값 설정
const UserContext = createContext({ //객체 안에 key, {}는 값
    /*   state: { id: 'aaa123', name: 'bbb' },
      action: {
          setUser: () => { }
      } 
      
     */ //확인을 하기 위한 모형일 뿐 없어도 실행 가능 
})

//2. Provider 정의 - 구조분해 할당은 반드시 children으로 키를 가지고 옴
const UserProvider = ({ children }) => {

    const [user, setUser] = useState({ id: 'aaa', name: 'bbb' });

    const value = {
        state: user,
        action: { setUser } //{setUser: setUser}도 맞는데 js의 빠른 할당 구문에 의해 줄여쓰기가 가능함
    }

    //console.log(children);
    //console.log(value);

    return (
        <UserContext.Provider value={value}>{children}</UserContext.Provider>
    )
}

//3. Consumer, provider 반환
const UserConsumer = UserContext.Consumer;

//부모에서는 UserProvider 사용하고, 자식에서는 UserConsumer 사용
export { UserProvider, UserConsumer }; //여러개를 반환할 때는 default말고 {}에 나열

//4. 기본 export
export default UserContext;
import { useContext, useRef } from "react";
import UserContext from "../contexts/ContextAPI2";

const A = () => {

    //초기값을 구조 분해 할당
    const { state, action } = useContext(UserContext);

    //useRef
    const input1 = useRef(null);
    const input2 = useRef(null);
    const handleClick = () => {
        //console.log(input1.current.value); //사용자의 입력값 
        //console.log(input2.current.value);

        //contextAPI의 action
        action.setUser({
            id: input1.current.value,
            name: input2.current.value
        });
    }

    return (

        /* 2nd - useContext 훅을 이용해서 처리 */
        <div>
            <h3>A 컴포넌트</h3>
            컨텍스트 안에 값: {state.id}<br />
            컨텍스트 안에 값: {state.name}<br />

            <div>
                <input type="text" ref={input1} />
                <input type="text" ref={input2} />
                <button onClick={handleClick}>컨텍스트 데이터 변경</button>
            </div>

        </div>

        /* 1st
        <UserConsumer>
            {
                (value) => (
                    <div>
                        <h3>A 컴포넌트</h3>
                        컨텍스트 안에 값: {value.state.id}<br/>
                        컨텍스트 안에 값: {value.state.name}<br/>
                    </div>
                )
            }
        </UserConsumer> 
        */
    )
}

export default A;
import { useContext } from "react";
import UserContext from "../contexts/ContextAPI2";
import C from "./C";
import D from "./D";

const B = () => {

    const { state, action } = useContext(UserContext);
    return (
        <>
            <h3>B 컴포넌트</h3>
            컨텍스트 안의 값: {state.id} <br />
            컨텍스트 안의 값: {state.name} <br />
            <C />
            <D />
        </>
    )
}

export default B;
import { useContext } from "react";
import UserContext from "../contexts/ContextAPI2";

const C = () => {

    const { state, action } = useContext(UserContext);
    return (
        <>
            <h3>C 컴포넌트</h3>
            컨텍스트 안의 값: {state.id} <br />
            컨텍스트 안의 값: {state.name} <br />
        </>
    )
}

export default C;
import { useContext, useRef } from "react";
import UserContext from "../contexts/ContextAPI2";

const D = () => {

    const { state, action } = useContext(UserContext);

    const input1 = useRef(null);
    const input2 = useRef(null);
    const handleClick = () => {
        //console.log(input1.current.value); //사용자의 입력값 
        //console.log(input2.current.value);

        //contextAPI의 action
        action.setUser({
            id: input1.current.value,
            name: input2.current.value
        });
    }
    return (
        <>
            <h3>D 컴포넌트</h3>
            컨텍스트 안에 값: {state.id}<br />
            컨텍스트 안에 값: {state.name}<br />

            <div>
                <input type="text" ref={input1} />
                <input type="text" ref={input2} />
                <button onClick={handleClick}>컨텍스트 데이터 변경</button>
            </div>
        </>
    )
}

export default D;

 

2. firebase에 react 배포하기

1) 배포의 단계

개발(develop) - 빌드(build) - 배포(deploy)

 

- 개발 : 만드는 단계

- 빌드 : 어플리케이션 가동의 필요한 것들을 통합하고, 경량화 시키는 단계 (배포를 위한 준비과정)

- 배포 : 서버에 반영을 하는 것

 

- 웹앱을 무료로 배포하는 다양한 방법이 존재합니다.

1]깃허브페이지

2] 구글 firebase

3] 기타 등등

- 이번에는 firebase를 이용해서 배포를 진행하도록 합니다.

 

2) 리액트 빌드하기

1] 프로젝트 최상위 루트에서 실행하세요.

npm run build

 

2] 실행하면 build폴더가 생성됩니다.

 

3] build폴더 안에는 개발 단계에서 복잡한 코드를 경량화해서 index.html을 생성해줍니다.

4] 바로 실행하게 되면 서버가 아니라서 정상적으로 실행이 안 될텐데요. 아래 명령어로 1회용 서버로 실행 시켜보세요.

 

설치 먼저 해주세요.

npx serve -s build

5] http://localhost:3000으로 들어가보면 빌드된 결과물이 나옵니다.

 

3) 파이어 베이스 배포하기

- 파이어베이스는 2011년 파이어베이스사가 개발하고 2014년 구글에 인수된 모바일 및 웹 애플리케이션 개발 플랫폼이다. 위키백과

1] firebase에 가입하고 콘솔로 이동합니다.

 

2] 프로젝트를 생성해 주세요.

3] hosting으로 들어갑니다.

4] 시작하기를 클릭해서 단계 별로 실행합니다. (firebase문서에 상세하게 나와있습니다^^) - 호스팅에서 시작하기 누르기

5] 컴퓨터에는 node.js가 설치되어야 합니다.

  • vs코드에서 아래 명령문을 실행합니다.
  • 프로젝트에 최상위 경로에서 진행해 주세요. (최상위 경로)

- 파이어베이스 설치

npm install -g firebase-tools

- 파이어베이스 로그인

npx firebase login

- 파이어베이스 설정시작

npx firebase init

- firebase 시작할거야? y

 

- 파이어 베이스에서 시작할 기능을 스페이스로 선택하세요.

- hosting을 선택합니다. (space선택 -> 엔터)

 

스페이스로 선택
첫번째 선택해서 엔터

 

선택하고 엔터

- 너의 기본 경로를 어디로 사용 할거에요? build

  • 리액트는 빌드시 폴더가 build로 생성되기 때문에 public폴더를 build로 잡아주세요 (디폴트 public)

- 싱글페이지 앱으로 구성할거에요? yes

- 깃허브에서 자동으로 배포하게 만들거에요? no

- index파일이 있는데 덮어쓸까요? no

  • yes를 선택하면 build했던 내용이 기본파일로 덮어집니다. 

 

 

- 마지막 질문: 덮어쓰면 기본으로 제공되는 화면이 나옵니다. 절대 덮지 말 것!

 

6] 파이어 베이스에 배포

npx firebase deploy

7] hosting url에서 확인하면 됩니다.

 

8] 이후에 배포는? - 업데이트 되는 내용들을 덮어서 배포해줌(빌드하고 올리고, 빌드하고 올리고)

  • npm run build (리액트 빌드)
  • npx firebase deploy (파이어베이스에 배포)만 하면됩니다.

'TIL > React' 카테고리의 다른 글

day71-react  (0) 2023.01.20
day70-react  (0) 2023.01.19
day69-react  (0) 2023.01.18
day68-react  (0) 2023.01.18
day67-react  (0) 2023.01.17
profile

mjeongriver

@mjeongriver

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그