본문 바로가기

배워서 따라하는 포플/예산 계산기 앱

예산 계산기 앱 - 함수형 컴포넌트 방식

클래스 컴포넌트를 함수형 컴포넌트로 변경

左) 클래스 컴포넌트 右) 함수형 컴포넌트

클래스 컴포넌트에서 함수형 컴포넌트로 수정할 때 기본구조를 우선 변경하겠습니다.

export class xx extends xx { render() { } } 부분 삭제한 후, const 파일이름 = () => { } 로 수정하면 됩니다.

 

左) 클래스 컴포넌트 생성자 右) 함수형 컴포넌트 함수

App.js의 생성자를 우측 사진처럼 변경해줍니다.

 

const [value, setValue] = useState("")

react문서를 보면,

value는 getter고 setValue는 setter입니다.

useState는 value, setValue를 리턴하고 초기 State값을 정하는 Hook이빈다.

 

App.js에서 이미 useState란 hook을 사용했으니 이전 클래스형인 this.state를 삭제합니다.

함수인만큼 앞에 const를 붙여줘야 하며, 방금 useState는 setter까지 있어서 바로 setExpenses로 적용하면 됩니다.

파일에서 해당 함수를 사용할 때는 this혹은 this.state는 모두 삭제하면 됩니다.

 

구조분해할당으로 ExpenseList, ExpenseItem.js파일에 사용하는 내용을 바로 가져와서 사용하면 됩니다.

 

지출 목록 추가 기능 생성하기

데이터들이 변경할 거라서 App.js에서 useState를 사용합니다.

작성하는 함수, 제출하는 함수도 만듭니다.

그리고 함수, 데이터들을 ExpenseForm으로 내려줍니다.

제출하는 함수 중 newExpenses는 React의 불변성을 고려해서 이렇게 추가한 겁니다.

ExpenseForm.js파일에 데이터, 함수를 받아오고, 각 이벤트가 발생하면 해당 함수를 실행합니다.

 

Alert 생성하기

const [alert, setAlert] = useState({show: false})

const handleAlert = ({type, text}) => {
    setAlert({show: true, type, text})
    setTimeout(() => {
      setAlert({show: false})
    }, 2000)
}

App.js에서 alert관련 state 및 함수를 만듭니다.

handleSubmit과 handleDelete함수 중 해당 handleAlert를 추가합니다.

{alert.show ? <Alert type={alert.type} text={alert.text}/> : null}

return의 main태그 안에 추가하는 부분입니다.

if조건문의 축약식입니다.

alert.show의 값이 true면 <Alert>를 추가하며, 아니면 null입니다.

여기서 Alert 컴포넌트 사용할 거니까 App.js파일 안에 import해야 합니다.

 

import React from 'react'
import './Alert.css'

const Alert = ({type, text}) => {
  return (
    <div className={`alert alert-${type}`}>{text}</div>
  )
}

export default Alert

components폴더 안에 Alert.js의 코드입니다.

.alert {
  padding: 0.75rem 1.25rem;
  color: var(--mainWhite);
  text-align: center;
  margin: 2rem auto 0 auto;
  border-radius: 2px;
}

.alert-danger {
  background: var(--mainRed);
}

.alert-success {
  background: var(--mainGreen);
}

components폴더 안에 Alert.css의 코드입니다.

 

총비용 계산하기(reduce메소드)

{expenses.reduce((acc, curr) => {
  return (acc += curr.amount)
}, 0)}

App.js파일에 총지출 부분 금액 계산하는 부분을 추가합니다.

reduce함수는 첫 번째 변수에 4개의 인자를 가집니다. 누산기(acc), 현재값(curr), 현재인덱스(idx), 원본배열(src)입니다.

두번째 변수는 초기값입니다.

 

지출 항목 수정기능 구현하기

const [id, setId] = useState("")
const [edit, setEdit] = useState(false)

const handleEdit = id => {
    const expense = expenses.find(item => item.id === id)
    const {charge, amount} = expense
    setId(id)
    setCharge(charge)
    setAmount(amount)
    setEdit(true)
}

App.js 파일에 함수를 먼저 선언합니다.

const handleSubmit = (e) => {
    e.preventDefault()
    if(charge !== "" && amount > 0) {
      if(edit) {
        const newExpenses = expenses.map(item => {
          return item.id === id ? {...item, charge, amount} :item
        })
        setExpenses(newExpenses)
        setEdit(false)
        handleAlert({type:"success", text: "아이템이 수정되었습니다."})
      }else{
        const newExpense = {id:crypto.randomUUID(), charge, amount}

        const newExpenses = [...expenses, newExpense]
        setExpenses(newExpenses)
        handleAlert({type:"success", text: "아이템이 생성되었습니다."})
      }
      setCharge("")
      setAmount() 
    }else{
      handleAlert({type:"danger", text: "charge는 빈값일 수 없으며 amount는 0보다 커야 합니다."})
    }
  }

기존에 있는 handleSubmit함수는 위와 같이 수정합니다.

ExpenseForm에 edit을 내려주고, ExpenseList에 handleEdit을 내려줍니다.

ExpenseForm.js파일에 제출 버튼을 조건문 방식으로 edit가 true면 수정으로 나타나고 아니면 제출로 나타납니다.

ExpenseList.js파일에 ExpenseItem에 handleEdit을 내려줍니다.

ExpenseItem.js파일에 수정 버튼 onClick 이벤트를 추가합니다.

 

전체 지출 항목 지우기 기능 구현하기

const clearItems = () => {
    setExpenses([])
}

App.js 파일에 함수를 먼저 선언합니다.

ExpenseList에 clearItems를 내려줍니다.

ExpenseList.js 기존에 버튼 부분을 위와 같이 수정했습니다.

빈 배열이 아니면 버튼 나타나는 구조입니다. 버튼을 클릭하면 빈 배열로 만듭니다.