minlog
article thumbnail

클래스형 컴포넌트 (Class Component )

1. 내보내기

1-1. default 내보내기

컴포넌트들은 보통 default로 내보낸다.

📑 App.js

import { Component } from "react"; //리엑트에서 Component 가져온다.
class App extends Component{
    render(){
        return (
            <main className="main-container">
                <h1>예산 계산기</h1>
                <div>

                </div>
            </main>
        )
    }
}

//내보내기 default - 메인으로 내보냄
export default App;

 

2-1. 클래스 바로 내보내기

여러개 내보낼 수 있다.

📑 App.js

import { Component } from "react"; //리엑트에서 Component 가져온다.
export class App extends Component{
    render(){
        return (
            <main className="main-container">
                <h1>예산 계산기</h1>
                <div>

                </div>
            </main>
        )
    }
}

export class AppB extends Component{
    render(){
        return (
            <div className="test-container">
                test
            </div>
        )
    }
}

받아오는 부분도 수정이 필요하다 { 이름 } 으로 변경해야한다.

📑 index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { App, AppB } from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </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();

 

 

2. 컴포넌트에 마크업에 style 적용하기

2-1. 인라인적용

<div style={{ width: '100%', background: 'white', padding: '1rem' }}>

import { Component } from "react"; //리엑트에서 Component 가져온다.
class App extends Component{
    render(){
        return (
            <main className="main-container">
                <h1>예산 계산기</h1>
                <div style={{width: '100%', background:'white',padding:'1rem'}}>
                    {/* Expense Form */}
                </div>
                <div style={{ width: '100%', background: 'white', padding: '1rem' }}>
                    {/* Expense list */}
                </div>
            </main>
        )
    }

}

//내보내기 default - 메인으로 내보냄
export default App;

 

2-2. css파일에 적용

📑App.css

.main-container{margin:0 auto;max-width:1280px;width:90%}

📑App.js

import { Component } from "react"; //리엑트에서 Component 가져온다.
import "./App.css"; // css 파일 연결
class App extends Component{
...
}
...

 

 

 

3. 컴포넌트 가져오기

3-1.여러개의 컴포넌트 생성

  • 컴포넌트 폴더를 만들어 내부에 필요한 컴포넌트들을 생성한다.
  • 컴포넌트 내용 구성 쉽게 구성하는 방법 rce

 

3-2.컴포넌트 연결

  • 컨포넌트를 가져온다. import 컨포넌트명 from "./components/ExpenseForm";
  • 컨포넌트명 은 항상 대문자로 시작해야한다.
  • 컨포넌트를 원하는 자리에 <컨포넌트명 /> 넣어준다.

📑 App.js

import { Component } from "react"; //리엑트에서 Component 가져온다.
import "./App.css";
import ExpenseForm from "./components/ExpenseForm"; // 1. 컨포넌트 가져오기

class App extends Component{
    render(){
        return (
            <main className="main-container">
                <h1>예산 계산기</h1>
                <div style={{width: '100%', background:'white',padding:'1rem'}}>
                    {/* Expense Form */}
                    <ExpenseForm /> // 2. 컨포넌트 넣기 
                </div>
                ...
            </main>
        )
    }

}

//내보내기 default - 메인으로 내보냄
export default App;

 

 

 

4. 리액트 아이콘 사용하기

리액트에서 아이콘을 사용하는 방법은 여러가지이지만 주로 rect-icons 모듈을 이용하여 아이콘을 구현한다.

4-1. 모듈설치

npm install react-icons

4-2. react-icons 사용방법

  • 사용할 js 파일에서 연결 import { MdSend } from 'react-icons/md'
  • 원하는 곳에 <MdSend> 추가
    더 자세한 사항과 아이콘 정보는 아래 사이트에서 확인할 수 있다.

https://react-icons.github.io/react-icons/

 

React Icons

React Icons Include popular icons in your React projects easily with react-icons, which utilizes ES6 imports that allows you to include only the icons that your project is using. Installation (for standard modern project) npm install react-icons --save Usa

react-icons.github.io

 

 

5. Props를 통해 컴포넌트 간 데이터 전달

  • Props 란 Properties의 줄임말이다.
  • Props 는 상속하는 부모 컴포넌트로부터 자녀 컴포넌트에 데이터 등을 전달하는 방법
  • Props 는 읽기 전용으로 자녀 컴포넌트 입장에서는 변하지 않는다. (변하려면 부모 컴포넌트에서 상태를 변경 시켜주어야한다.)

부모 컴포넌트 => 자녀 컴포넌트

 

5-1. 부모컴포넌트 데이터 전달방법

  • 데이터 생성 : initialExpenses =[...]
  • 데이터 전달 : <전달할컴포넌트 initialExpenses={this.initialExpenses}/>

📑App.js

iimport { Component } from "react"; //리엑트에서 Component 가져온다.
import "./App.css";
import ExpenseForm from "./components/ExpenseForm";
import Expenselist from "./components/Expenselist";


class App extends Component{

    initialExpenses =[
        { id: 1, charge: "렌트비", amount: 16000 },
        { id: 2, charge: "교통비", amount: 20000 },
        { id: 3, charge: "숙박비", amount: 200000 },
        { id: 4, charge: "식비", amount: 56000 }
    ]

    render(){
        return (
            <main className="main-container">
                <h1>예산 계산기</h1>
                <div style={{width: '100%', background:'white',padding:'1rem'}}>
                    ...
                </div>
                <div style={{ width: '100%', background: 'white', padding: '1rem' }}>
                    {/* Expense list */}
                    <Expenselist initialExpenses={this.initialExpenses}/>
                </div>

                    ...
            </main>
        )
    }

}

//내보내기 default - 메인으로 내보냄
export default App;
</div>

 

5-2. 자녀 데이터 받는 방법

  • 데이터 가져오기: this.props.initialExpenses

📑Expenselist.js

render() {
      console.log(this.props.initialExpenses);
    return (
      <>
        <ul className='list'>
            <ExpenseItem />
        </ul>
        <button className='btn'>
            목록지우기
                <MdDelete className='btn-icon'></MdDelete>
        </button>
      </>
    )
  }

 

5-3.Map 메서드를 사용한 데이터 반환

배열내의 모든 요소 각각에 대하여 주어진 함수 호출 결과를 새로운 배열로 반환하는 것

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map

 

Array.prototype.map() - JavaScript | MDN

map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

developer.mozilla.org

  • 데이터 전달 : map 을 사용해 각각의 아이템을 ExpenseItem에 'expense={expense}'전달 해주고 있다.
  • 키속성 명시 : 해당 아이템의 유니크 값을 넣어주어야한다. key={expense.id}

JSX key 속성이란?
리액트에서 요소의 리스트 나열시 key를 넣어줘야한다.
키는 리액트가 변경,추가 또는 제거된 항목을 식별하는데 도움이 된다. (가상돔 -> 변경 내역 -> 실제 돔 적용)
요소의 안정적인 ID를 부여하려면 배열 내부의 요소에 키를 제공해야한다.

이때 키로는 index는 비 추천되는 방법이다. 이유는 리스트가 추가되거나 제거 되면 리스트들의 key값도 변경되게 된다.

 

📑Expenselist.js

import React, { Component } from 'react'
import './ExpenseList.css'
import ExpenseItem from './ExpenseItem'
import { MdDelete } from 'react-icons/md'

export class Expenselist extends Component {
  render() {
      console.log(this.props.initialExpenses);
    return (
      <>
        <ul className='list'>
            {this.props.initialExpenses.map(expense=>{
                return (
                    <ExpenseItem expense={expense} key={expense.id}/>
                )
            })}
        </ul>
        <button className='btn'>
            목록지우기
                <MdDelete className='btn-icon'></MdDelete>
        </button>
      </>
    )
  }
}

export default Expenselist

 

5-4. 각 아이템 받아오기

  • 각 속성을 사용하여 아이템 요소 가져오기 : {this.props.전달데이터명.키이름}

📑ExpenseItem.js

import React, { Component } from 'react'
import './ExpenseItem.css'
import { MdEdit, MdDelete } from 'react-icons/md'

export class ExpenseItem extends Component {
  render() {
    return (
      <>
        <li className='item'>
            <div className='info'>
                    <span className='expense'>{this.props.expense.charge}</span>
                    <span className='amount'>{this.props.expense.amount}원</span>
            </div>
            <div>
                <button className='edit-btn'><MdEdit /></button>
                    <button className='clear-btn'><MdDelete /> </button>
            </div>
        </li>
      </>
    )
  }
}

export default ExpenseItem

 

 

 

6. Filter 메소드를 사용한 리스트 삭제 기능

Filter 메서드
주어진 함수의 테스트를 통과하는 모든요소를 모아 새로운 배열로 반환

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

 

Array.prototype.filter() - JavaScript | MDN

filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.

developer.mozilla.org

 

6-1. 부모컴포넌트 함수 전달

  • 이벤트 함수 생성 : handleDelete=(매개변수)=>{처리과정}
  • 자식컴포넌트 전달 : Expenselist 컴포넌트에 handleDelete={this.handleDelete} 함수 전달
  • filter 메서드 사용 : 기존 리스트 배열 initialExpenses에 연결하여 각 요소와 전달받은 id 값을 비교 일치 하지 않는 것만 새로운 배열로 만들어준다.

📑App.js

// 클릭 이벤트 함수 생성
// 아이템 제거
handleDelete = (id) => {
  const newExpenses = this.initialExpenses.filter(expect=> expect.id !== id);
  console.log(newExpenses)
}

render(){
        return (
            <main className="main-container">
                <h1>예산 계산기</h1>
                ...
                <div style={{ width: '100%', background: 'white', padding: '1rem' }}>
                    {/* Expense list */}
                    <Expenselist initialExpenses={this.initialExpenses} handleDelete={this.handleDelete} />
                </div>
                ...
            </main>
        )
    }

 

6-2. 자식컴포넌트 이벤트 재 전달

  • 컴포넌트로 데이터 재 전달 : 실제 요소가 있는 ExpenseItem 컴포넌트에 전달받은명칭={this.props.전달받은명칭} 으로 재 전달한다.

📑Expenselist.js

...

export class Expenselist extends Component {
  render() {
      console.log(this.props.initialExpenses);
    return (
      <>
        <ul className='list'>
            {this.props.initialExpenses.map(expense=>{
                return (
                    <ExpenseItem 
                        expense={expense}
                        key={expense.id}
                        handleDelete={this.props.handleDelete}  // 전달 
                    />
                )
            })}
        </ul>
        ...
      </>
    )
  }
}

export default Expenselist

 

6-3. 실제 사용되는 컴포넌트에서 처리

  • 버튼클릭 이벤트 추가 : 버튼 태그에 onClick이벤트를 추가해준다.
  • 부모컴포넌트에서 전달 받은 함수 사용 : this.props.handleDelete(this.props.expense.id) 전달받은 함수를 가져와 사용한다.
    📑ExpenseItem.js
    ...
    export class ExpenseItem extends Component {
    render() {
      return (
        <>
          <li className='item'>
              ...
              <div>
                  <button className='edit-btn' 
                      onClick={()=>
                          this.props.handleDelete(this.props.expense.id)
                      }
                  ><MdEdit />
                  </button>
                  ...
              </div>
          </li>
        </>
      )
    }
    }

 

 

 

⭐ 7. React State  화면변화 리랜더링!

리액트에서 데이터가 변할 때 화면을 다시 렌더링 해주기 위해서는 React State 를 사용해야한다.
React State란
컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 갖고 있는 객체로 컴포넌트 안에서 관리된다.
State 가 변경되면 컴포넌트는 리랜더링 된다.

기억해야하는 데이터를 State를 이용하여 기억시켜야한다.

 

7-1. State를 사용하여 데이터 기억

App.js 파일에서 기존에는 데이터를 배열로 생성만 해주었는데, State를 생성해서 내부에 기억 시켜주는 로직으로 변경 해주었다.

  • State 생성 : 클래스 내부에 추가해준다. constructor(props){ ... this.state={ 데이터이름 :[{데이터},{},{}]} = > ※ 하위설명 참고
  • State 데이터 사용 : State 내부에 생성한 데이터는 this.state.데이터이름 으로 사용될 수 있다.
  • State 데이터 상태 변경시 적용 : this.setState({ 데이터이름 : 변경된데이터 }) 이와 같이 변화 시켜 줄 수 있다.

📑App.js


class App extends Component{
 //1. State 생성
constructor(props){ 
  super(props);
  this.state ={
    expenses: [ // 이름
      { id: 1, charge: "렌트비", amount: 16000 },
      { id: 2, charge: "교통비", amount: 20000 },
      { id: 3, charge: "숙박비", amount: 200000 },
      { id: 4, charge: "식비", amount: 56000 }
    ]
  }
}


 // 클릭 이벤트 함수 생성
 handleDelete = (id) => {
    const newExpenses = this.state.expenses.filter(expect=> expect.id !== id); //2-1. State 사용
    this.setState({ expenses : newExpenses }) //3. State 변화 적용

  }


  render(){
        return (
            <main className="main-container">
                ...
                <div style={{ width: '100%', background: 'white', padding: '1rem' }}>
                    {/* Expense list */}
                    <Expenselist initialExpenses={this.state.expenses} handleDelete={this.handleDelete} />//2-2. State 사용
                </div>
                ...
            </main>
        )
    }
    ...

 

 

※ State 생성 더 깊게 알아보기 ==> 자바와 동일한 문법

1. Constructor `constructor` 생성자를 사용하면 인스턴스화 된 객체에서 다른 메서드를 호출하기 전에 수행해야 하는 사용자 지정 초기화를 제공할 수 있다.

  • 초기에 생성되어야 하는 것들을 지정.
  • 이렇게 생성된 변수는 this.명칭 으로 바로 사용가능하다.

2. super : 부모클래스 호출 => 부모클래스 생성
리액트에서 super로 props를 인자로 전달하는 이유는 React.Component 객체가 생성될때 props 속성을 초기화 하기 위해 전달한다.

constructor(props){ 
  super(props);
  this.state ={
    expenses: [ // 이름
      { id: 1, charge: "렌트비", amount: 16000 },
      { id: 2, charge: "교통비", amount: 20000 },
      { id: 3, charge: "숙박비", amount: 200000 },
      { id: 4, charge: "식비", amount: 56000 }
    ]
  }
}
profile

minlog

@jimin-log

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