배포의 단계

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

개발 - 만드는 단계

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

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

 

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

  1. 깃허브페이지
  2. 구글 firebase
  3. 기타등등

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


리액트 빌드하기

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

npm run build

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

 

 

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

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

 

 

npx serve -s build

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

 


파이어베이스 배포하기

 

파이어베이스는 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 (파이어베이스에 배포)만 하면됩니다.

 

'Front-End > React' 카테고리의 다른 글

10. 리액트 ContextAPI  (0) 2023.01.02
9. Ajax로 외부 데이터 통신하기  (0) 2022.12.29
8. React라우터  (0) 2022.12.28
7. React에 CSS적용하기  (0) 2022.12.27
6. 리액트 기본훅  (0) 2022.12.26

데이터를 전역으로 관리하자 ContextAPI or Redux

API문서

https://ko.reactjs.org/docs/context.html

 

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

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

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

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

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

 

 

 

 

https://velopert.com/3606

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

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

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

 

이런 문제는

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

 

 

 

 

ConextAPI 사용방법

 

createContext() 훅 

  • ContextAPI를 생성합니다.
const 사용할이름 = createContext(초기값)

 

provider와 consumer

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

 

구현순서

  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;

 


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;

'Front-End > React' 카테고리의 다른 글

11. firebase에 react배포하기  (0) 2023.01.04
9. Ajax로 외부 데이터 통신하기  (0) 2022.12.29
8. React라우터  (0) 2022.12.28
7. React에 CSS적용하기  (0) 2022.12.27
6. 리액트 기본훅  (0) 2022.12.26

프로미스는 자바스크립에 내장된 내장객체 입니다
프로미스 객체에서는 2가지를 형태를 지닙니다.

 

1. 상태(state) 

  • pending : 수행중
  • fullfilled : 성공적 완료
  • rejected : 실패

2. 프로듀서 - 정보를 제공하는 제공자(즉, Promise)
    컨슈머 - 사용자(즉, 호출하는사람)

 


프로미스 생성
executor콜백함수를 전달해야 하며 executor콜백함수는 다시 resolve함수와 reject함수를 받습니다.

//매개변수는 컨슈머가 분명 콜백함수를 전달할거야!(그 콜백함수로 리턴해줄게!)
let promise = new Promise( (success, fail) => {

    //producer 입장에서 성공했을 때 성공을 알리는 함수
    success("success"); 

    //producer 입장에서 실패했을 때 실패를 알리는 함수
    //fail(new Error("fail"));

});

console.log(promise)

프로미스의 사용 then(), catch()

  • then은 promise가 정상적으로 실행 된다면, 결과를 실행시켜주는 콜백함수이다.
  • catch는 promise가 실패했을 때, 결과를 실행시켜주는 콜백함수이다.
//....생략
promise.then( data => console.log(data) )
       .catch( error => console.log(error) )

프로미스의 적용

결과가 언제 돌아갈지 모르지만, 내가 이것을 완료되면 Promise를 전달해 줄테니, 너는 then함수만 이용해서 결과를 받아서 처리해!

 

ajax fetch()의 내부모습 예시

//자바스크립트로 구현되어있는 fetch라고 가정
function myfetch(req) { 
    //비동기적 실행.. 10초..
    return new Promise( (success, fail) => {
        success("data....");
    });
}

//fetch와 같은 실행구조를 보인다.
myfetch("http://localhost:5502/~~~~~").then( response => console.log(response) );

 


Promise를 더 쉽게 사용할 수 있게 해주는 async(이거 비동기야)

async, await규칙

  1. 어싱크 함수 안에서 어웨잇을 사용한다
  2. function 앞에 async 키워드를 추가 함수는 언제나 프라미스를 반환 합니다.
  3. 리턴이 프로미스라면 await을 적용하고 then절을 없앨 수 있다.

 

async란 function앞에 선언하며, return값을 자동으로 Promise로 변경해주는 역할을 한다.
즉, 비동기 함수의 실행 형태로 변경해준다.

async function myfetch(req) {
    //비동기적 실행.. 10초..
    return "data....";
}


//var result = myfetch()
//console.log(result); //Promise

myfetch("http://localhost:5502/~~~~~").then( response => console.log(response) );

 

Promise를 더 쉽게 사용할 수 있게 해주는 await(기다려)

리턴이 프로미스라면 await을 적용하고 then절을 없앨 수 있다. (단 async함수 안에서만 사용 가능합니다)

(async function() {
    let data = await myfetch();
    console.log(data)

})();

async, await의 장점

  1. 코드의 간결성
  2. 어싱크, 어웨잇은 동기적방식(순서를) 보장한다

 

 

'Front-End > JavaScript(ES6)' 카테고리의 다른 글

JS ES6 문법 한눈에 보기  (0) 2022.12.20

목차

  1. Ajax란?
  2. ES6의 fetch를 이용해서 리액트에서 데이터 처리하기
  3. Axios로 데이터 처리하기 
  4. async, await 적용하기

 

AJAX ( Asynchronous Javascript and XML) 은 웹 페이지의 이동없이 필요한 데이터만 전송하는 기술입니다.

 

ajax

웹 어플리케이션에서 데이터를 가져올 때 서버쪽 데이터가 필요할 때 ajax기법을 사용하게 됩니다.

이 작업은 시간이 오래 걸릴 수도 있기 때문에 비동기적으로 처리하게 됩니다.

비동기(asynchronous)는 요청이 끝날 때 까지 기다리는 것이 아니라, 동시에 여러 작업을 수행하게 됩니다.

 

나중에 react에서는 다른 서버의 REST API와 통신을 이용하여 데이터베이스 데이터를 가져올 수 있습니다.

 


ES6의 fetch를 이용해서 리액트에서 데이터 처리하기

Promise = fetch(요청주소)

 

1. 이벤트 클릭시 처리하기

  • 데이터를 가져와서 useState()에 저장하는 작업입니다.
  • 극단적으로 표현해 데이터 통신에 100초 가 소요되면 useState는 100초 간 undefined 상태가 됩니다.
  • 렌더링 시에 에러를 나타내기 때문에, undefined에 관한 처리를 동시에 진행합니다.

 

import { useEffect, useState } from "react";

const App = () => {

    let [raw, setRaw] = useState();

    const handleClick = () => {
        fetch('https://raw.githubusercontent.com/yopy0817/data_example/master/hi.json')
        .then( response => response.json() )
        .then( data => {
            //console.log(data)
            setRaw(data)
        })
    }

    return (
        <div>
            <h3>클릭시에 fetch로 데이터 가져오기</h3>
            <button type="button" onClick={handleClick}>데이터로드</button>
            {raw !== undefined ?
                <div>
                    {raw.userId}<br />
                    {raw.userPw}<br />
                    {raw.userName}<br />
                </div>
                : undefined
            }
        </div>
    )

}

export default App;

2. 화면 렌더링 완료시 데이터 처리하기 useEffect() 훅 사용

  • 비동기 작업을 컴포넌트에 바로 쓰고 state를 변경하면, 무한루프에 빠지게 됩니다.
  • 그래서 useEffect() 훅을 이용하여 첫번째 렌더링 완료시만 데이터만 가져오도록 처리합니다.
import { useEffect, useState } from "react";

const App = () => {

    let [data, setData] = useState()

    //렌더링 완료시 데이터 로드
    useEffect( () => {
        fetch('https://raw.githubusercontent.com/yopy0817/data_example/master/hi.json')
        .then( response => response.json() )
        .then( data => {
            setData(data)
        })
    }, [])


    return (
        <div>
            <h3>로딩시에 fetch로 데이터 가져오기(같은표현)</h3>
            {data && <div>
                        {data.userId}<br />
                        {data.userPw}<br />
                        {data.userName}<br />
                    </div>
            }
        </div>
    )

}

export default App;

Axios로 데이터 처리하기

엑시오스는 비동기를 더편하게 처리하는 라이브러리 입니다.
 
엑시오스 설치
npm add axios

엑시오스

Promise = axios.get(요청주소)

 

1. 이벤트 클릭시 처리하기 (fetch와 거의 같음 😊)

import axios from "axios";
import { useState } from "react";

const App = () => {

    const handleClick = () => {
        axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/hi.json')
        .then(response => {
            setData( response.data );
        })
    }

    return (
        <div>
            <h3>엑시오스데이터</h3>
            <button type="button" onClick={handleClick}>데이터로드</button>
            {data !== undefined ?
                <div>
                    {data.userId}<br />
                    {data.userPw}<br />
                    {data.userName}<br />
                </div>
                :
                undefined
            }
        </div>
    )
}
export default App;

async(이거 비동기임) , await(기다려) 적용하기

ES6의 문법입니다. 비동기 코드를 간결하게 작성할 수 있게 합니다.

 

구문의 내용을 잘모르거나 궁금하면 여기로
https://coding404.tistory.com/21

 

async, await규칙

  1. 어싱크 함수 안에서 어웨잇을 사용한다
  2. function 앞에 async 키워드를 추가 함수는 언제나 프라미스를 반환합니다.
  3. 리턴이 프로미스라면 await을 적용하고 then절을 없앨 수 있다.

 

비동기에서 3번의 데이터 통신을 한다고 가정합시다.

1,2,3,4,5,6의 순서로 출력될 것 같지만 아닙니다.

순서를 보장하지 않습니다.

    ...생략
    const handleClick = () => {
        axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/hi.json')
        .then(response => {
            console.log(response.data);
            console.log(1)
        })
        console.log(2)

        axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/hello.json')
        .then(response => {
            console.log(response.data);
            console.log(3)
        })
        console.log(4)
        
        axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/by.json')
        .then(response => {
            console.log(response.data);
            console.log(5)
        })
        console.log(6)
    }

Axios는 이미 Promise를 반환합니다.

Axios앞에 await을 사용할 수 있고, then() 절을 생략 할  수 있습니다.

Axios를 호출하는 부모함수에는 await을 반드시 달아줍니다.

 

async, await의 장점

  1. 코드의 간결성
  2. 어싱크, 어웨잇은 동기적방식(순서를) 보장한다

 

async, await적용하여 변경하기

const handleClick = async () => {
    let response = await axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/hi.json')
    console.log(response.data);
    setData( response.data );

    console.log(1);

    let response2 = await axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/hello.json')
    console.log(response2.data);

    console.log(2);

    let response3 = await axios.get('https://raw.githubusercontent.com/yopy0817/data_example/master/by.json')
    console.log(response3.data);

    console.log(3);

}

 

'Front-End > React' 카테고리의 다른 글

11. firebase에 react배포하기  (0) 2023.01.04
10. 리액트 ContextAPI  (0) 2023.01.02
8. React라우터  (0) 2022.12.28
7. React에 CSS적용하기  (0) 2022.12.27
6. 리액트 기본훅  (0) 2022.12.26

SPA란? (single page application)

하나의 페이지로 만들어진 어플리케이션을 의미합니다.

 

전통적 웹 어플리케이션 vs SPA

 

SPA는 html파일을 브라우저 측에서 로드하고, 필요한 데이터는 API와 ajax통신을 이용해서 처리합니다.

브라우저에서 사용자가 상호작용 하면 필요한 부분만 업데이트 해서 처리합니다.

멀티플랫폼 Android, IOS에 대응하여 웹뷰로 처리하는 목적으로도 사용됩니다.

 

SPA의 단점

  • 앱의 규모가 커지면, JS파일도 너무 커져서 로딩이 오래걸리게 됩니다.
  • 브라우저에서 렌더링이 완료되기 까지 비어있는 화면이 나오게 됩니다.
  • 그래서 규모가 큰 어플리케이션은 SSR(서버사이드 렌더링) 방식으로 처리합니다. (웹팩 설정 필요)

 

라우팅이란?

  • 브라우저의 주소상태에 따라 다양한 화면을 보여주도록 처리하는 것을 라우팅이라고 합니다.

 

사용이유

  • create-react-app로 프로젝트를 생성하게 되면 기본적으로  SPA에 CSR(클라이언트 렌더링) 입니다.
  • 하나의 페이지만 사용하게 되는 것입니다.
  • SPA이지만 라우터를 활용해서 사용자로 하여금 여러 페이지가 존재하는 것처럼 느껴지게 할 수 있습니다.

라우터 설치하고 프로젝트 시작하기

1. 라우터를 적용할 프로젝트 생성

npm create react-app 프로젝트명

2. 라우터 설치

npm add react-router-dom

3. 프로젝트 시작

npm start

라우터 적용하기

  1.  라우터를 사용할때는 index.js에서 App컴포넌트를 <BrowserRouter>로 감싸줍니다.
  2.  페이지 컴포넌트 만들기
  3.  App컴포넌트에서 <Routes>를 사용해서 분기하기
  4.  주소요청을 통해 확인하기

index.js

....
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>

);

 

 

App.js

  • /요청은 Home컴포넌트가 나타납니다
  • /user요청은 User컴포넌트가 나타납니다.
  • /info요청은 Info컴포넌트가 나타납니다.
function App() {

  return (
    <Routes>
        <Route path='/' element={<Home/>}/>
        <Route path='/user' element={<User/>}/>
        <Route path='/info' element={<Info/>}/>
    </Routes>
  );
}

export default App;

Link를 이용해서 다른페이지로 이동하기

  • link태그는 화면에서 a태그로 생성됩니다.
  • to 속성에는 연결할 요청주소를 적습니다.
  • 어느 컴포넌트든 사용할 수 있습니다.

/로 연결되는 Home

//.....
return (
	<ul>
		<li><Link to='/user'>회원페이지</Link></li>
	</ul>
)

URL파라미터 or 쿼리스트링

같은 컴포넌트라도 전달되는 데이터에 따라서 다른 내용을 보여줘야 하는 경우가 있습니다.

EX) 글 상세

이 때 URL주소의 매개변수를 전달 할 수 있고, 컴포넌트는 그 값을 받아서 사용 할 수 있습니다.

 

1. 쿼리스트링

  • 쿼리스트링은 주소의 ? 뒤에 키=값 의 형태로 넘어가는 매개값입니다.
  • 별도의 라우터 설정은 하지 않아도 됩니다.
  • 컴포넌트에서는 useLocation() 훅 or useSearchParams() 훅을 사용 해서 쿼리스트링을 받을 수 있습니다.
/경로?키=값&키=값

 

링크에서는...

//.....
return (
	<ul>
		<li><Link to='/user?id=aa123&key=1'>회원페이지(쿼리파람)</Link></li>
	</ul>
)

 

컴포넌트에서는....

 

 useLocation() 훅

const location = useLocation();   
 
 
useSearchParams() 훅 
 
  • 배열을 반환합니다.
  • 첫 번째 요소는 쿼리파라미터를 조회하거나 수정하는 get, set이 담긴 객체
  • 두 번째 요소는 쿼리파라미터를 객체로 업데이트 하는 함수 반환
const [객체, function] = useSearchParams() 
    const [obj, setObj] = useSearchParams();
    let id = obj.get("id"); //request.getParameter("키")
    let key = obj.get("key");

2. URL파라미터 👍

  • URL파라미터는 주소 뒤에 /경로/값/값 의 형태로 넘어가는 매개값입니다.
  • 라우터에 추가적인 설정이 필요합니다. ( /주소/:키 )
  • 컴포넌트에서는 useParams() 훅을 사용하여 URL파라미터를 받을 수 있습니다.

 

라우터에서는...

function App() {

  return (
    <Routes>
        .....
        <Route path='/info/:num' element={<Info/>}/>
    </Routes>
  );
}

export default App;

링크에서는...

 

//.....
return (
	<ul>
		<li><Link to='/info/1'>1번 info</Link></li>
		<li><Link to='/info/2'>2번 info</Link></li>
		<li><Link to='/info/3'>3번 info</Link></li>
	</ul>
)

 

컴포넌트에서는...

 

useParams() 훅

 

/param에는 link로 넘어온 키가 담겨 있습니다.

let param = useParams();

중첩라우터로 공통 부분 처리하기

  • 글페이지가 있고, 글에 따른 상세화면이 있다고 가정해 봅시다.
  • 라우터의 설정은 아래 처럼 보여질 수 있습니다.
  • 아래 설정은 두 라우터가 다르기 때문에 각각 다른 화면이 보입니다.
<Routes>
	<Route path='/board' element={<Board/>}/>
	<Route path='/board/:num' element={<BoardContent/>}/>
</Routes>

  • 만약 Board 목록 페이지를 공통으로 사용하고 상세페이지를 서브로 보여주도록 처리하려면 중첩라우터를 활용할 수 있습니다.
  • 중첩라우터로 적용되면 부모컴포넌트에서 <Outlet> 컴포넌트를 활용해서 하위 라우터를 보여지게 할 수 있습니다.
<Routes>
	<Route path='/board' element={<Board/>}>
		<Route path=':num' element={<BoardContent/>}/>
	</Route>
</Routes>

 

Board에서는...

const Board = () => {

    return (
        <div>
            <h3>게시글목록</h3>
            <ul>
                <li><Link to='/board/1' >글1</Link></li>
                <li><Link to='/board/2' >글2</Link></li>
                <li><Link to='/board/3' >글3</Link></li> 
             </ul>

            {/* Oulet컴포넌트가 사용된 자리에 중첩된 내용이 보여지게됩니다 */}
            <Outlet/>
        </div>
    )
}

export default Board;

 

BoardContent에서는...

const BoardContent = () => {

    let {num} = useParams()

    return (
        <div>
            <h3>글 상세페이지</h3>
            {num}번 글입니다      
        </div>
    )
}

export default BoardContent;

 

결과


헤더 태그 분리하기

 


라우터의 부가적인 기능

1. NavLink 컴포넌트

  •  링크에서 사용하는 경로가 라우터의 경로와 일치하면 특정스타일을 적용 (활성화기능)

 

2. useNavigate() 훅 vs Navigate 컴포넌트 

useNavigate() 훅

  • JS의 history객체를 대신합니다.
  • 이벤트에서 사용

Navigate 컴포넌트 

  • 리다이렉트기능 
  • 렌더링시에 사용

 


NavLink컴포넌트 

  • NavLink는 링크의 경로가 라우터의 경로와 일치하면 특정스타일을 적용해 줍니다.
  • NavLink는 style속성을 제공하합니다
  • style속성에는 실행시킬 함수를 작성합니다.
  • 이 함수에 매개변수로 {isActive : boolean}객체를 넣어주는데, 활성화 여부를 표시가 가능합니다.
  • 사용은 반드시 {isActive}변수로 구조분해할당 합니다.

 

Board컴포넌트 에서는...

 

const Board = () => {

    return (
        <div>
            <h3>게시글목록</h3>
            <ul>
                {/* 
                <li><Link to='/board/1' >글1</Link></li>
                <li><Link to='/board/2' >글2</Link></li>
                <li><Link to='/board/3' >글3</Link></li> 
                */}
                <li><NavLink to='/board/1' style={
                    ({isActive}) => {
                    return isActive ? myStyle : undefined  
                    }
                }>글1</NavLink></li>
                <li><NavLink to='/board/2' style={({isActive}) => (isActive ? myStyle : undefined  )}>글2</NavLink></li>
                <li><NavLink to='/board/3' style={({isActive}) => (isActive ? myStyle : undefined  )}>글3</NavLink></li> 
            
             </ul>

            {/* Oulet컴포넌트가 사용된 자리에 중첩된 내용이 보여지게됩니다 */}
            <Outlet/>
        </div>
    )
}

export default Board;

 


useNavigate() 훅

  • useNavigate훅 은 특정 event가 발생할 때,  url을 조작할 수 있는 함수를 제공합니다.
  • react v6 에서 useHistory 가 변화한 것입니다. (JS의 history객체를 대신 합니다)
let navigator = useNavigate();
import { Fragment } from "react";
import { NavLink, Outlet, useNavigate } from "react-router-dom";

const Header = () => {
    //useNavigate() 훅
    let nav = useNavigate();

    const goHome = () => {
        nav('/내가원하는 주소') 
    }
    return (
    	<button onClick={goHome}>이동</button>
    )

}
export default Header;

JS의 history를 다루는 기능도 제공합니다.

예시) history.go(-1) 

예시) history.go(1) 

  ...
  let nav = useNavigate();
  
  return(
      <>
          <button onClick={() => nav(-1)}>
            Go back
          </button>
          <button onClick={() => nav(1)}>
            Go forward
          </button>
      <>
  )

Navigate 컴포넌트

  • <Navigate> 컴포넌트는 렌더링 될 때 현재 위치를 변경합니다.
  • useNavigate()훅과 비슷해보이지만 useNavigate()훅은 렌더링 과정에 사용할 수 없습니다.
const MyPage = () => {
    /*
    렌더링 과정에 nav를 쓰지말라는 경고 후 작동이 안됩니다.
    let nav = useNavigate()
    let loginYN = false;
    if(!loginYN) {
        nav('/');
    }
    */
	
    //Navigate컴포넌트
    let loginYN = false;
    if(!loginYN) {
        return <Navigate to='/' replace={true}/>
    }

    return (
        <div>
            여기는 권한있는 사람만 들어옴
        </div>
    )

}
export default MyPage;

'Front-End > React' 카테고리의 다른 글

10. 리액트 ContextAPI  (0) 2023.01.02
9. Ajax로 외부 데이터 통신하기  (0) 2022.12.29
7. React에 CSS적용하기  (0) 2022.12.27
6. 리액트 기본훅  (0) 2022.12.26
5. 컴포넌트 반복  (0) 2022.12.23

리액트 스타일링

1. 태그에 직접 지정하기

2. 일반 css파일로 적용하기

3. css모듈로 적용하기

 

css파일 이름 규칙

컴포넌트의 이름을반드시 포함해서 만듭니다
EX) App.js - App.css
 

1. 태그에 직접 디자인을 적용 할 때는 {}로 묶어줍니다 
  •  css속성중 - 은 카멜표기법으로 대체됩니다.
style={{css속성: 값, css속성: 값}}
<p style={{color: 'white', textAlign: 'center'}}>안녕하세요!!</p>

2. 일반CSS문법으로 디자인을 해주면 되고 import로 가져오면 됩니다.

 

App.css

.app_header {
    height: 50px;
    line-height: 50px;
    background-color: #000;
    margin: 0;
    padding: 0;
}

App.js

import './css/App.css'; //일반css파일로 디자인
......생략

3. CSS모듈사용하기

  • 파일은 컴포넌트명.module.css 형식으로 만듭니다.
  • css파일은 import구문으로 가져옵니다.
  • 이 방식은 선택자에 고유한 해시값을 부여함으로 다른파일과 디자인의 중복을 막아줍니다.
  • :global 키워드를 이용해서 전역 선택자(이름) 선언이 가능합니다.

App.module.css 파일

.app_wrap {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    text-align: center;
    background-color: #fff;
    height: 100vh;
    margin: 0;
    padding: 0;
}

/* 전역선택자로 이름정하기 */
:global .title {
    color: pink;
    font-weight: 900;
}

App.js 파일

  1. css파일은 특정 이름으로 import합니다.
  2. style={특정이름.선택자 로} 적용합니다.
  3. :global 키워드는 이름으로 바로 사용하면 됩니다.
import styled from './css/App.module.css'; //css모듈로 디자인

const App = () => {
    return (
        <Fragment>
            <section className={styled.app_wrap}> {/* css모듈 app_wrap적용 */}
                 <p className="title">CSS모듈로디자인!</p> {/* css모듈의 전역선택자 적용 */}
            </section>
        </Fragment>
    )
}

export default App;

 

'Front-End > React' 카테고리의 다른 글

9. Ajax로 외부 데이터 통신하기  (0) 2022.12.29
8. React라우터  (0) 2022.12.28
6. 리액트 기본훅  (0) 2022.12.26
5. 컴포넌트 반복  (0) 2022.12.23
4. 리액트 이벤트 핸들링  (0) 2022.12.21

훅(HOOK) 이란?

  1. 리액트 컴포넌트는 클래스형 컴포넌트(Class component)와 함수형 컴포넌트(Functional component)로 나뉩니다.
  2. 리액트 훅은 새로운 기능으로 React 16.8버전에 새로 추가된 기능
  3. 함수형태의 컴포넌트에서 사용되는 몇가지 기술을 Hook이라고 부른다. (useState, userEffect 등)
  4. 리액트 훅은 함수형 컴포넌트가 클래스형 컴포넌트의 기능을 사용할 수 있도록 해주는 기능이다.

훅의 규칙

  • 최상위 에서만 Hook을 호출해야 한다
    • 반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안된다.
    • 이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장된다.
  • 리액트 함수 컴포넌트에서만 Hook을 호출해야 한다.

 

 

반드시 알아야 할 기본 훅

useState(초기값) 

useState() : 배열반환 
첫번째 배열의 요소에는 현재값을, 두번째 요소는 상태를 변경하는 (setter) 를 반환합니다.
 

const [data, setData] = useState('초기값')

useEffect(실행시킬 콜백함수, 값에 따른 렌더링 지정 ) 

userEffect의 첫번째 매개변수는 실행시킬 콜백함수

userEffect의 두번째 매개변수는 배열[]을 사용하여 특정값이 update 될 때만 실행시켜 줄 수 있습니다.

 

useEffect() 는 컴포넌트의 라이프 사이클을 다룹니다.
리액트 컴포넌트가 mount, mount이후, unmount때 마다 특정작업을 수행합니다.

라이프 사이클

mount 이후 - 컴포넌트가 마운트 됨, 즉 컴포넌트의 첫번째 렌더링이 마치면 호출되는 메서드 입니다.

클래스형 componentDidMount() 대체

함수형 훅

useEffect( () => {
	console.log(`렌더링완료`);
});

 

mount 이후 업데이트 될 때는 실행되지 않으려면, 두번째 매개변수 배열를 줍니다.

 

useEffect( () => {
	console.log(`처음만 실행됩니다`);
}, []);​

update 이후 - 특정값에 의해 컴포넌트가 업데이트 되고 난 후 발생합니다.

클래스형 componentDidUpdate() 대체

함수형 훅

const HookEffect = () => {
    //useState
    const[name, setName] = useState('');
    const handleName = (e) => {
        setName( e.target.value );
    }

    //특정값이 업데이트 될 때만 실행해주려면 두번째 매개변수에 값을 state값을 지정합니다
    useEffect( () => {
        console.log(`name이 업데이트 시 실행됩니다`)
    }, [name]);

    return (
        <div>
            
            이름:<input type="text" onChange={handleName}/><br/>
            이름:{name}
        </div>
    )
}

export default HookEffect;

unmount직전 - 컴포넌트가 화면에서 사라지기 직전에 호출됩니다.

클래스형 componentWillUnMount() 대체

함수형 

const HookEffect = () => {
    //useState
    const[name, setName] = useState('');
    const handleName = (e) => {
        setName( e.target.value );
    }
    
	//useEffect    
    useEffect( () => {
        console.log(`name이 업데이트 시 실행됩니다`)
        
        //unmount이후 실행됩니다.
        return () => {
            console.log(`unmount에 실행됩니다.`);
        }
    }, [name]);

    return (
        <div>
            이름:<input type="text" onChange={handleName}/><br/>
            이름:{name}
        </div>
    )
}

export default HookEffect;

특정 태그에 이름달기 useRef()

useRef(초기값) 
const 사용할이름 = useRef(null);

 

이벤트를 사용하다 보면 특정 태그에 접근해서 핸들링 하는 경우가 생깁니다.

arrow function에 event 매개변수를 이용해서, 자신 태그에는 접근할 수 있지만, 다른태그는 핸들링 하기가 어렵습니다.

이런경우 useRef() 훅을 이용해서 특정태그에 이름을 지정하고 핸들링 할 수 있습니다.

 

const HookRef = () => {
    //useState
    const [form, setForm] = useState({data: '', result: '' });
    //useRef
    const inputTag = useRef(null);
    //인풋핸들링
    const handleChange = (e) => {
        setForm( {data :e.target.value} ); //인풋값이 변할때마다 data변수 변화
    }
    
    //버튼핸들링 - 클릭시 state는 변경하고, input태그에 포커스
    const handleClick = (e) => {
        setForm( {data: '', result: form.data})
        //useRef의사용 - current로 ref의 현재태그에 접근가능
        inputTag.current.focus()
    }

    return (
        <div>
            할일: <input type="text" value={form.data} onChange={handleChange} ref={inputTag} />
            <button type="button" onClick={handleClick}>등록하기</button>

            <br/>
            결과: {form.result}

        </div>
    )
}

export default HookRef;

훅의 종류는 이뿐이 아니고 굉장히 많습니다.

추후 필요한 hook들은 추가 되거나 뒤에서 학습합니다.

'Front-End > React' 카테고리의 다른 글

8. React라우터  (0) 2022.12.28
7. React에 CSS적용하기  (0) 2022.12.27
5. 컴포넌트 반복  (0) 2022.12.23
4. 리액트 이벤트 핸들링  (0) 2022.12.21
3. 리액트 State  (0) 2022.12.21
  1. 목록 요소들을 반복처리 할때는 map함수를 이용 합니다.
  2. 반복 컴포넌트에는 반드시 key props를 전달해야 합니다.

 

map함수는 실행한 결과를 가지고 새로운 배열을 만들 때 사용

array.map(callbackFunction(currenValue, index, array), thisArg) 
  • currenValue: 현재값
  • index: 현재인덱스
  • arrayt: 현재배열,
  • thisArg: callbackFunction 내에서 this로 사용될 값

 

filter - 요소개수만큼 반복하며 boolean을 이용한 새로운 list를 만듬

array.filter(callbackFunction(currenValue, index, array), thisArg) 
  • currenValue: 현재값
  • index: 현재인덱스
  • arrayt: 현재배열,
  • thisArg: callbackFunction 내에서 this로 사용될 값
const IterationComponent = () => {

    const arr = [1,2,3,4,5];
    const newArr = arr.map( item => item*10 ) // => 한줄일 경우 리턴

    console.log('map으로 생롭게 만들어진 newArr', newArr)
	
    return (
    	....
    )
}

map의 콜백함수의 리턴에 반복시킬 태그를 넣습니다.

리액트에서 key는 배열을 렌더링 시킬때 빠르게 변화를 감지하기 위해 사용하는 속성입니다.

key는 index대신 고유한 값을 넣어 주도록 권유 됩니다. (key를 넣지 않으면 props에러가 발생 됩니다.)

const IterationComponent = () => {

    const arr = [1,2,3,4,5];
    const newArr = arr.map((item, index) => <li key={index}>{item}</li>)

    return (
        <ul>
            {newArr}
        </ul>
    )
}

export default IterationComponent;

 

반복할 요소를 state에 넣고 처리하기

버튼 클릭시 인풋state의 값을 목록state에 추가하기

1. 반복처리할 state선언
2. input state, 인풋 핸들러선언
3. 버튼 클릭시 input state의 값을 목록state에 추가
import { useState } from "react";


const IterationComponent2 = () => {

    //1. 반복처리할 데이터 state
    const data = [{id:1, topic: 'hello'},
                  {id:2, topic: 'bye'} 
                 ];
    const [list, setList] = useState(data)
    const newData = list.map( item => <li key={item.id}>{item.topic}</li> )

    //2.인풋핸들러추가
    const [inputData, setInputData] = useState('')
    const handleChange = e => {
        setInputData(e.target.value) //input데이터 state로 관리
    }

    //3. 데이터 추가시 input의 값으로 1번 데이터 수정
    const handleClick = e => {
        let obj = {id: list[list.length-1].id + 1 , topic: inputData} //추가할데이터(마지막요소의 id+1, 인풋데이터)
        let newList = list.concat(obj) //state와 추가할 데이터 합치기(배열합치기)
        setList(newList); //state업데이트
        setInputData(''); //input값 비우기
    }

    return (
        <div>
            <hr/>
            <input type="text" onChange={handleChange} value={inputData}/>
            <button onClick={handleClick}>추가하기</button>
            <ul>
                {newData}
            </ul>
        </div>
    )

}

export default IterationComponent2;

 

 

 

 

 

 

'Front-End > React' 카테고리의 다른 글

7. React에 CSS적용하기  (0) 2022.12.27
6. 리액트 기본훅  (0) 2022.12.26
4. 리액트 이벤트 핸들링  (0) 2022.12.21
3. 리액트 State  (0) 2022.12.21
2. 리액트의 Components와 props  (0) 2022.12.21

+ Recent posts