TIL 2023-01-03 리액트 컴포넌트

JYR00·2023년 1월 3일
0

TIL

목록 보기
53/60

프로젝트 java505_react_test3 생성


package.json


필요한 의존성 프로그램들을 넣어주는 파일.


react 용 bootstrap이 따로 존재함
https://react-bootstrap.github.io/

하지만 동작방법이 다르기 때문에 기존 부트스트랩 가져올 거임(버튼 실행하려면 import 사용해야 한다)

https://getbootstrap.com/

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
            crossorigin="anonymous"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" 
          integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" 
          crossorigin="anonymous">

리액트용 부트스트랩 적용하고 싶다면?

node.js는 반드시 폴더 안에 들어가 그 밑에 패키지를 설치해야 한다.

절대로 이런 상태로 실행하면 안된다

PS C:\java505\intellij\react\java505_react_test3> npm install react-bootstrap bootstrap


생긴 건 똑같다.

<button type={"button"}>기본 버튼</button>
        <button type={"button"} className={"btn btn-primary"}>부트스트랩 적용 버튼</button>
        <Button type={"button"} variant={"success"}>react용 bootstrap 적용 버튼</Button>
        {/*리액트 용 방법은 좀 다르다. react용 button은 대문자로 시작된다. 소문자로 적은건 html태그로 인식한 것이고
        대문자로 시작한 건 리액트 컴포넌트로 인식한 것이다.*/}

컨텍스트



jsx문법

<></>이것도 인식한다. 부모태그 바깥에 있으면 오류가 남.

App.js

import logo from './logo.svg';
import './App.css';
import Button from 'react-bootstrap/Button';

// 기본적으로 7가지를 알아야 한다
// JSX : 자바스크립트 + html / xml , 하나의 파일에 js와 html을 동시에 작성
// 컴포넌트 : 리액트를 구성하는 최소 ui단위, 데이터(props)를 입력받아 view(state) 상태에
//          따라 화면을 출력하는 함수, 컴포넌트 이름은 항상 대문자로 시작한다.(리액트는 소문자로 시작하는 컴포넌트를 html태그로 인식한다)
//          ui를 재사용 가능한 개별적인 여러 조각으로 나누어서 화면 구현

// 컴포넌트의 종류 2가지
// 함수형 컴포넌트 : 현재 많이 사용되는 방식, 사용이 간편함, 자바스크립트 함수를 작성하는 방식
// 클래스형 컴포넌트 : 기존에 많이 사용되는 방식, React.Component를 상속받아 구현함, 컴포넌트 구성요소,
//                  리액트 생명주기를 모두 포함하고 있음
// props : 컴포넌트 간의 데이터를 주고 받기 위한 객체, properties의 줄임말, 읽기 전용, 부모 컴포넌트에서
//          자식 컴포넌트로 데이터를 전달 시 주로 사용
// state : 현재 컴포넌트의 상태를 표시하는 객체, setState()를 통해서 데이터를 수정, 데이터 수정 시 화면에
//          재랜더링이 됨
// hooks : react 16.8 버전에서 추가된 기능, 상태 변경 및 리액트 생명주기에 관련된 함수를 사용할 수 있게 해주는 기능.
//          리액트 hooks를 사용하면 클래스 컴포넌트를 사용할 필요가 없음
// 컨텍스트 : 데이터 전달 객체, 컴포넌트간의 데이터 전달 시 props를 사용하면 순차적으로 데이터를 전달함,
//          컨텍스트는 위치에 상관없이 데이터를 바로 전달할 수 있음. 원래는 1번 컨테이너에 들어가고 싶다면
//          전체 -> main -> 1이런 순으로 들어가야 하는데, 컨텍스트를 거치면 어느 곳이든 바로 들어갈 수 있다
// react-router : 각 페이지의 경로를 구성하는 라이브러리.



// JSX 문법
// 1. 반드시 1개의 부모 요소가 다른 요소를 감싸는 형태로 구성해야 함
// 리액트는 가상화면을 미리 만들어놓고 다 만드면 실제 화면에 뿌리는 형태이기 때문에 부모 요소가 하나만 존재한다
// 2. 자바스크립트 표현식 사용 가능
//    {} 안에 자바스크립트를 사용할 수 있다.
//    if문은 표현식이 아니기 때문에 jsx에서 사용할 수 없다 (삼항 연산자를 대신 사용)
// 3. html 속성을 카멜명명법으로 사용해야 한다
// font-size => fontSize로 사용함
// class => className 으로 사용





function App() {
    let num1 = 10;
    const flag = false;
    let result;
    
    //여기서는 if문 사용이 가능하다
    // {}표현식 내에서 자바스크립트의 if문을 사용할 수 없으므로 외부에서 미리 연산한다
    if (flag){
        result = <div>결과가 true</div>
    }
    else{
        result = <div>결과가 false</div>
    }

    return (

        // <></> 이것도 태그로 인식한다.
        // <p>안뇽</p>
    //    꼭 div태그를 사용해야 하는 건 아님(부모태그로) 그래도 가장 무난한 건 div다.
    <div className="App">


        <br/><hr/>
        <button type={"button"}>기본 버튼</button><br/>
        <button type={"button"} className={"btn btn-primary"}>부트스트랩 적용 버튼</button><br/>
        <Button type={"button"} variant={"success"}>react용 bootstrap 적용 버튼</Button>

        <p>{num1 + 10}</p>

        {/*if문을 사용하면 바로 에러가 난다.*/}
        {/*{if(flag){*/ } 
        {/*    */}
        {/*}}*/}

        {/*아래와 같은 삼항연산자를 if문 대신 사용해야 한다*/}
        {flag == true ? 1100 : 0}

        {/*두 개중 어느 것을 골라도 동일하게 출력이 된다*/}
        {result}
        <div>{result}</div>


        {/*리액트 용 방법은 좀 다르다. react용 button은 대문자로 시작된다.
        소문자로 적은건 html태그로 인식한 것이고
        대문자로 시작한 건 리액트 컴포넌트로 인식한 것이다.*/}
        <br/><hr/>
        <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
            Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
        >
            Learn React
        </a>
        </header>



    </div>
    );
}

export default App;



컴포넌트 사용하기



대부분 함수 컴포넌트를 많이 사용하는 편이다.

ClassComponetn.jsx

// ClassComponetn.jsx
// js로 해도 작동은 잘 된다

// 1. 모든 컴포넌트는 React를 import해서 사용함
// 2. class 컴포넌트는 React.Component를 상속받아 클래스를 생성
// 3. 클래스 컴포넌트를 export default로 설정해야 내부에서 사용가능하다
// 4. 클래스 컴포넌트에는 render() 메서드가 존재한다. render() 함수에서 jsx문법을 사용함
// 5. 클래스 컴포넌트는 리액트 생명주기 메서드를 사용할 수 있음
// 6. 생성자 사용 가능. 생성자에서 상태표현을 위해 state를 설정


import React from "react";

class ClassComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state={}
    }
    
    render() {
        return(
            <div>
                <p>클래스 컴포넌트 화면</p>
            </div>
        );
    }
    
    componentDidMount() {
        console.log("마운트 후 출력")
    }
}

export default ClassComponent;

FunctionComponent.jsx

// FunctionComponent.jsx

// 1. 모든 컴포넌트는 React를 import해서 사용함
// 2. 함수 컴포넌트는 그냥 함수 생성
// 3. 함수 컴포넌트를 export default로 설정해야 내부에서 사용가능하다
// 4. 함수 컴포넌트는 return에서 jsx문법을 사용한다
// 5. state 변경 및 생명주기에 관련된 함수를 사용하기 위해서 hooks를 사용함

// 대부분 function 컴포넌트에서 해결함. HOOK을 사용하면서 생명주기 사용가능해졌기 때문


import React ,{useState} from "react";

function FunctionComponent(props){
    return (
        <p>함수컴포넌트 사용</p>
    );
}

export default FunctionComponent;

index.js에 을 주석처리하고 를 넣어준다.

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App2';
import reportWebVitals from './reportWebVitals';
import App2 from "./App2";
import App3 from "./App3";
import App33 from "./App33";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
    {/*<App />*/}
    {/*    <App2/>*/}
        <App3/><-!!!!!!!!!!!! 지금 App3를 사용한다
                  
    {/*    <App33/>*/}
    </React.StrictMode>

);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

그 때 그 때 필요한 폴더를 연결하고 있다

✨StrictMode란 react 앱 내의 잠재적인 문제를 알아내기 위한 도구이다.

App3.jsx

//App3.jsx
import React from "react";
import ProFileList from "./folder1/ProfileList";
import BoardList from "./folder1/BoardList";

function App3(){
    return(
        <div>
            <ProFileList/>
            <br/>
            <BoardList/>

        </div>
    );
}

export default App3;

이곳에서 여러 파일들을 모아 화면을 만들어 주고 있다.

ProFileList.jsx

// ProFileList.jsx

import React from "react";
import Profile from "./Profile";


// props : 컴포넌트 간의 데이터 전달을 위해서 사용하는 자바스크립트 객체. 읽기 전용이다.
// 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달 시 사용한다.
// 부모 컴포넌트에서 자식 컴포넌트를 호출하여 사용 시 속성을 사용하여 데이터를 전달한다.
// 부모 컴포넌트에서 사용한 속성명이 자식 컴포넌트의 props 객체에 담겨서 전달이 된다.
// 해당 속성명을 자식 컴포넌트에서 그대로 사용함

function ProFileList(){
    return(
        <div className={"row"}>
            <div className={"col-sm-6 mx-auto"}>
                <Profile userId = {"test1"} userName={"테스터1"} userTel={"01012345678"} userEmail={"test1@naver.com"}/>
                <Profile userId ={"test2"} userName={"테스터2"} userTel={"01011111111"} userEmail={"test2@naver.com"}/>
            </div>
        </div>
    );
}
export default ProFileList;

prifile의 데이터를 가져온다

BoardList.jsx

// BoardList.jsx

import React from "react";
import BoardItem from "./BoardItem";

const boardItemList = [
   {boardIdx : 100, boardTitle: "게시판 글 제목 100번", boardUserId : "test1",  boardCreateDate:"2023-01-03-12:40:00"},
   {boardIdx : 101, boardTitle: "게시판 글 제목 101번", boardUserId : "test2",  boardCreateDate:"2023-01-03-12:41:00"},
   {boardIdx : 102, boardTitle: "게시판 글 제목 102번", boardUserId : "test3", boardCreateDate:"2023-01-03-12:43:00"},
]

function BoardList(){
   // boardItemList.map((item )=>{
   //    return <BoardItem idx ={item.boardIdx} title={item.boardTitle} userId={item.boardUserId} createDt={item.boardCreateDate}/>
   // })
   return(
       <div className={"container mx-5 mx-auto" }>
           <table className={"table table-hover table-striped"}>
               <thead>
               <tr>
                   <th>글 번호</th>
                   <th>글 제목</th>
                   <th>사용자</th>
                   <th>등록시간</th>
               </tr>
               </thead>
               <tbody>
               {/*하나하나 다 넣기 힘드니까 데이터는 리스트로 넘어오니 for문으로 반복해 집어넣어준다*/}
               {boardItemList.map((item )=>{
                       return <BoardItem idx ={item.boardIdx} title={item.boardTitle} userId={item.boardUserId} createDt={item.boardCreateDate}/>
               })}
               
                   {/*<BoardItem idx={"100"} title={"테스트 제목100"} userId={"test1"} createDt={"2023-01-03 12:40:00"}/>*/}
                   {/*<BoardItem idx={"101"} title={"테스트 제목101"} userId={"test2"} createDt={"2023-01-03 12:40:00"}/>*/}
                   {/*<BoardItem idx={"102"} title={"테스트 제목102"} userId={"test3"} createDt={"2023-01-03 12:40:00"}/>*/}
               </tbody>
           </table>
           <BoardItem/>
       </div>
   );
}
export default BoardList;

///////////////////////////////////

{boardItemList.map((item )=>{
                     return <BoardItem idx ={item.boardIdx} title={item.boardTitle} userId={item.boardUserId} createDt={item.boardCreateDate}/>
             })}
             

데이터 하나하나 넣어주기 힘드니 반복문을 사용해 집어 넣어준다.

map


파라미터로 전달된 함수를 사용해, 배열 각 요소를 원하는 규칙에 따라 변환한 다음 새로운 배열을 생성한다.

BoardItem.jsx

// BoardItem.jsx

import React from "react";

function BoardItem({idx, title, userId, createDt}){
  return(
      <tr>
          <td>{idx}</td>
          <td>{title}</td>
          <td>{userId}</td>
          <td>{createDt}</td>
      </tr>
  );
}
export default BoardItem;

Profile.js

//Profile.js

import React from "react";


// function Profile({userId, userName,userTel,userEmail}){} 이런 식으로 해도 된다.
// 확장표현식 - 대입연산자 오른쪽의 데이터를 연산자 왼쪽의 변수에 저장시 [] / {} 에 표시된 이름에 대입
// 왼쪽이 오브젝트타입이면 오른쪽이 오브젝트타입이어야 한다. 단! key 값이 동일해야 한다


// 컴포넌트 => 함수다
function Profile(props){
  let data = props;
  //props는 읽기전용이므로 계산이나 변경하고 싶으면 변수로 받아 해야 한다.

  let userId = props.userId;
  let userName = props.userName;
  let userTel = props.userTel;
  let userEmail = props.userEmail;

  return (
      <div className={"border rounded-2 px-3 m-4"}>
          <div className = {"my-3" }>
              <label for={"user-id"} className={"form-label"}>아이디 : </label>
              <input type={"text"} id={"user-id"} className={"form-control"} value={data.userId}/>
              {/*<input type={"text"} id={"user-id"} className={"form-control"} value={props.userId}/>*/}
          </div>
          <div className = {"my-3" }>
              <label for={"user-name"} className = {"form-label" }>이름 : </label>
              <input type={"text"} id={"user-name"} className={"form-control"} value={userName}/>
          </div>
          <div className = {"my-3" }>
              <label for={"user-tel"} className = {"form-label" }>전화번호 : </label>
              <input type={"tel"} id={"user-tel"} className={"form-control"} value={props.userTel}/>
          </div>
          <div className = {"my-3" }>
              <label for={"user-email"} className = {"form-label" }>이메일 : </label>
              <input type={"email"} id={"user-email"} className={"form-control"} value={userEmail}/>
          </div>
      </div>
  )
}

export default Profile;




















0개의 댓글