본문 바로가기

2024. 06. 05 (수) 6주차 - Daily Coding - Day03

@Breadbread22024. 6. 5. 15:46
반응형

29강

- Form 제출하기

- Two-way binding(현업에서 많이 쓰이는 개념)

 

Form 제출하기

<form>에는 onSubmit(메서드) 이벤트 리스너가 있어서 form의 제출 이벤트를 핸들링하고,

이 이벤트를 발생하기 위해서는 <button type = 'submit>이 필요하다.

 

event.preventDefault()

해당 event에서 기본적으로 실행되는 로직을 실행되지 않게 하고 싶은 경우

즉, 강제로 해당 실행을 막을 때 사용한다고 보면 된다.

ex)

1. a 태그 클릭 시 href 링크로 이동 => 해당 링크로 이동을 막는다

2. form의 submit을 클릭 시 새로 실행이 됨 => submit을 눌러도 아무런 실행이 되지 않게 됨

 

const buttonSubmitHander = (event_) => {

     event.preventDefault();

     console.log(objectState);

};

  

Two-way binding

만약 form을 제출하고 값을 초기화 해주고 싶을때 하기 순서로 작업한다.

 

1. input에 상태를 value 속성으로 넣어준다.

2. 제출을 한 후에 상태를 초기화 진행한다.

3. value에 초기화된 상태가 반영되어 UI에 업데이트 한다.

  const buttonSubmitHandler = (event) => {
    // console.log('name', objectState.name)
    // console.log('price', objectState.price)
    // console.log('today', objectState.today)
    event.preventDefault(); // form이 submit될 때마다 기본적으로 설정 된 새로고침 기능을 막아줌.
    
    console.log(objectState);

    setObjectState({
      name: '',
      price: 0,
      today: new Date(),
    })
  }
<div className='new-payment__control'>
  <label>이름</label>
  <input type='text'
  value={1111} 
  onChange={inputTypeTextChangeHandler}/>
</div>

// value에 1111 을 넣어줌으로써 하드코딩이 되어 버림.

 

30강

자식 컴포넌트 < - > 부모 컴퍼넌트

부모 컴퍼넌트에서 함수 만들고 props를 통해 자식 컴포넌트에게 전달 한다.

 

부모 컴퍼넌트

import "./App.css";
import PaymentForm from "./components/PaymentForm/PaymentForm";
import Expenses from "./components/Payments/Expenses";

function App() {
	const expenses = [
		{
			id: "e1",
			title: "수건",
			amount: 12.33,
			date: new Date(2025, 8, 14),
		},
	];


	const getPaymentFormData = (data) => {
		console.log(data);
	}

	return (
		<>
			<PaymentForm  getPaymentFormData = {getPaymentFormData}/>
			<Expenses items={expenses} />
		</>
	);
}

export default App;

 

자식 컴포넌트

import React, { useState } from "react";

import "./PaymentForm.css";

const PaymentForm = ({getPaymentFormData}) => {
	const [objectState, setObjectState] = useState({
		name: "",
		price: 0,
		today: new Date(),
	});

	const inputTextHandler = (event) => {
		setObjectState((prevState) => ({
			...prevState,
			name: event.target.value,
		}));
	};

	const inputPriceHandler = (event) => {
		setObjectState((prevState) => ({
			...prevState,
			price: event.target.value,
		}));
	};

	const inputTodayHandler = (event) => {
		setObjectState((prevState) => ({
			...prevState,
			today: event.target.value,
		}));
	};

	const buttonSubmitHander = (event) => {
		event.preventDefault();

		getPaymentFormData(objectState)
		//console.log(objectState);

		setObjectState({
			name: "",
			price: 0,
			today: new Date(),
		});
	};

	return (
		<div className="new-payment">
			<form onSubmit={buttonSubmitHander}>
				<div className="new-payment__controls">
					<div className="new-payment__control">
						<label>이름</label>
						<input
							type="text"
							onChange={inputTextHandler}
							value={objectState.name}
						/>
					</div>
					<div className="new-payment__control">
						<label>금액</label>
						<input
							type="number"
							min="0.01"
							step="0.01"
							onChange={inputPriceHandler}
							value={objectState.price}
						/>
					</div>
					<div className="new-payment__control">
						<label>날짜</label>
						<input
							type="date"
							min="2019-01-01"
							max="2023-12-31"
							onChange={inputTodayHandler}
							value={objectState.today}
						/>
					</div>
				</div>
				<div className="new-payment__actions">
					<button type="submit">결제 추가</button>
				</div>
			</form>
		</div>
	);
};

export default PaymentForm;

 

 

31강

- 이미지 파일 가져오기

- 이미지 파일의 종류

- 파일 크기에 따른 이미치 처리 방식

 

참고자료

https://github.com/dev-owen/react-fundamental/tree/practice/3-7

 

 

jpg, jpeg

- 높은 압축률

- 이미지 퀄리티가 손상 될 수 있음(Lossy)

- 수천가지 팔레트 색

- 사진, 로고, 라인X

 

pns

- 손실 없이 이미지를 압축(Lossless)

- W3C 권장 표준

- 간단한 배너 이미지에 적합

 

svg

- 2차원 벡터 그래픽

- 해상도 상관없이 이미지 품질이 좋음

- 로고, 라인 

- 복잡한 이미지 X

 

이미지 용량에 따른 브라우저에서 처리

브라우저

alexa.png(4KB)

[<image src = "data:image/png...">]

 

siri.png(57KB)

[img src="/static/media/siri.png"/>]

 

 

개발 서버(dev server)

[index.html]

[bundle.js (alexa.png)] < 9.7KB : inlined

// alexa.png파일이 9.7KB보다 작아서 base64로 인코딩해서 보여주는 거임.

 

[siri.png] > 9.7KB separated files

 

이미지 크기를 조절하기

<img> 태그에서 with, heightdml 값을 조정한다.

<style> 속성에서 with, height 값으로 조절한다.

function App() {
  return (
    <div>
      <p>hello image</p>
      <img src="{AlexaImage}" alt="alexa" with={500} height={500}/>
      <img 
        src="{SiriImage}"
        alt="siri"
        style={{with: 500, height: 500}}/>
    </div>
  );
}

 

✔️중요

이미지 파일의 크기가 9.7KB (1000byte)기준으로 큰지 작은지에 따라 이미지 파일을 브라우저에서 처리하는 방식이 달라진다.


30강 오류 해결 방법

부모 컴포넌트 -> 자식컴포넌트 전달

강의대로 하면 아래와 같은 오류가 발생한다

ERROR props.date.getFullYear is not a function TypeError: props.date.getFullYear is not a function

data: data.date 가 아니라 data: new Date(data.today) 로 해줘야 오류가 발생하지 않는다.

// 부모 컴포넌트

import { useState } from "react";
import "./App.css";
import PaymentForm from "./components/PaymentForm/PaymentForm";
import Expenses from "./components/Payments/Expenses";

function App() {
	const [expenses, setExpenses] = useState([
			{
				id: "e1",
				title: "수건",
				amount: 12.33,
				date: new Date(2025, 8, 14)
			},
	])

	const getPaymentFormData = (data) => {
		setExpenses([
			{
			id: Math.random().toString(),
			title: data.name,
			amount: data.price,
			date: new Date(data.today)
		},
	]);
	};

	return (
		<>
			<PaymentForm  getPaymentFormData = {getPaymentFormData}/>
			<Expenses items={expenses} />
		</>
	);
}

export default App;
//자식 컴포넌트

import React, { useState } from "react";
import "./PaymentForm.css";

const PaymentForm = ({getPaymentFormData}) => {
	const [objectState, setObjectState] = useState({
		name: "",
		price: 0,
		today: new Date(),
	});

	const inputTextHandler = (event) => {
		setObjectState((prevState) => ({
			...prevState,
			name: event.target.value,
		}));
	};

	const inputPriceHandler = (event) => {
		setObjectState((prevState) => ({
			...prevState,
			price: event.target.value,
		}));
	};

	const inputTodayHandler = (event) => {
		setObjectState((prevState) => ({
			...prevState,
			today: event.target.value,
		}));
	};

	const buttonSubmitHander = (event) => {
		event.preventDefault();

		getPaymentFormData(objectState)
		//console.log(objectState);

		setObjectState({
			name: "",
			price: 0,
			today: new Date(),
		});
	};

	return (
		<div className="new-payment">
			<form onSubmit={buttonSubmitHander}>
				<div className="new-payment__controls">
					<div className="new-payment__control">
						<label>이름</label>
						<input
							type="text"
							onChange={inputTextHandler}
							value={objectState.name}
						/>
					</div>
					<div className="new-payment__control">
						<label>금액</label>
						<input
							type="number"
							min="0.01"
							step="0.01"
							onChange={inputPriceHandler}
							value={objectState.price}
						/>
					</div>
					<div className="new-payment__control">
						<label>날짜</label>
						<input
							type="date"
							min="2019-01-01"
							max="2023-12-31"
							onChange={inputTodayHandler}
							value={objectState.today}
						/>
					</div>
				</div>
				<div className="new-payment__actions">
					<button type="submit">결제 추가</button>
				</div>
			</form>
		</div>
	);
};

export default PaymentForm;
반응형
Breadbread2
@Breadbread2 :: 혼자만의 시간은 좋지만, 혼자는 싫다냐옹 (건들지 말라옹)

안녕하세요~! 저의 블로그를 방문해주셔서 감사합니다!! 좋은 정보 많이 많이 공유할게요~! 자주 놀러와주세요!

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차