카테고리 없음
240205_React
Seungyeon.Jung
2024. 2. 5. 16:47
import React, { useState } from "react";
function SignUp(props) {
const [name, setName] = useState("");
const [gender, setGender] = useState("비공개");
const handleChangeName = (event) => {
setName(event.target.value);
}
const handleChangeGender = (event) => {
setGender(event.target.value);
}
const handleSubmit = (event) => {
alert(`이름: ${name}, 성별:${gender}`);
event.preventDefault();
};
return (
<form onSubmit={handleSubmit}>
<label>
이름 :
<input type="text" value={name} onChange={handleChangeName}/>
</label>
<br/>
<label>
성별 :
<select value={gender} onChange={handleChangeGender}>
<option value="남자">남자</option>
<option value="여자">여자</option>
<option value="비공개">비공개</option>
</select>
</label>
<button type="submit">제출</button>
</form>
);
}
export default SignUp;
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
// import App from './App'; 주석처리
import reportWebVitals from './reportWebVitals';
import SignUp from './chapter_11/SignUp';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<SignUp/>
</React.StrictMode>
);
reportWebVitals();
1. 상태 초기화:
- useState를 사용하여 name 상태 변수를 초기화합니다. name은 현재 빈 문자열로 초기화됩니다.
const [name, setName] = useState("");
2. 입력 값 변경:
- 입력란에 값을 입력할 때마다 handleChangeName 함수가 호출됩니다.
- 입력 값이 변경될 때마다 setName을 통해 name 상태가 업데이트됩니다.
const handleChangeName = (event) => {
setName(event.target.value);
}
3. 폼 제출:
- 폼이 제출되면 handleSubmit 함수가 호출됩니다.
- alert 창이 팝업되며 "이름: 익명의 하마"라는 메시지가 표시됩니다.
const handleSubmit = (event) => {
alert(`이름: ${name}`);
event.preventDefault();
};
4. 페이지 갱신 방지:
- event.preventDefault()를 호출하여 기본 제출 동작을 방지합니다. 이로써 페이지가 새로고침되지 않고 상태가 유지됩니다.
5. 렌더링:
- 최종적으로 폼 요소가 화면에 렌더링되고, 사용자가 입력한 값에 따라 화면이 업데이트됩니다.
const scaleNames = {
c: "섭씨",
f: "화씨",
};
function TemperatureInput(props) {
const handleChange = (event) => {
props.onTemperatureChange(event.target.value);
};
return (
<fieldset>
<legend>온도를 입력해주세요 (단위:{scaleNames[props.scale]}):</legend>
<input value={props.temperature} onChange={handleChange}></input>
</fieldset>
);
}
export default TemperatureInput;
import React, { useState } from "react";
import TemperatureInput from "./TemperatureInput";
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p> 물이 끓습니다. </p>;
}
return <p> 물이 끓지 않습니다. </p>
}
function toCelsius(fahrenheit) {
return ((fahrenheit - 32) * 5 )/9;
}
function toFahrenheit(celsius) {
return (celsius * 9) / 5 + 32;
}
function tryConvert(temperature, convent) {
const input = parseFloat(temperature);
if(Number.isNaN(input)) {
return "";
}
const output = convent(input);
const rounded = Math.round(output * 1000) / 1000;
return rounded.toString();
}
function Calculator(props) {
const [temperature, setTemperature] = useState("");
const [scale, setScale] = useState("c");
const handleCelsiusChange = (temperature) => {
setTemperature(temperature);
setScale("c");
};
const handleFahrenheitChange = (temperature) => {
setTemperature(temperature);
setScale("f");
}
const celsius =
scale === "f" ? tryConvert(temperature, toCelsius) : temperature;
const fahrenheit =
scale === "c" ? tryConvert(temperature, toFahrenheit) : temperature;
return (
<div>
<TemperatureInput
scale="c"
temperature={celsius}
onTemperatureChange={handleCelsiusChange}
></TemperatureInput>
<TemperatureInput
scale="f"
temperature={fahrenheit}
onTemperatureChange={handleFahrenheitChange}></TemperatureInput>
<BoilingVerdict celsius={parseFloat(celsius)}></BoilingVerdict>
</div>
);
}
export default Calculator;
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import Calculator from './chapter_12/Calculater';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Calculator/>
</React.StrictMode>
);
reportWebVitals();
- 사용자가 "섭씨" 입력 필드에 100을 입력합니다.
- TemperatureInput 컴포넌트의 <input> 엘리먼트에서 onChange 이벤트가 발생합니다.
- handleChange 함수가 호출되어 사용자가 입력한 값(100)이 이벤트 객체에서 추출됩니다.
- props.onTemperatureChange(event.target.value)를 통해 상위 컴포넌트인 Calculator의 handleCelsiusChange 함수가 호출됩니다.
- handleCelsiusChange 함수는 입력된 섭씨 온도(100)를 setTemperature 함수를 통해 상태로 설정하고, 동시에 온도의 단위를 "섭씨"로 설정합니다.
- useState 훅에 의해 상태가 변경되면 React는 해당 컴포넌트를 리렌더링합니다.
- Calculator 컴포넌트가 리렌더링되면서 섭씨 온도(100)에 따른 화씨 온도가 계산됩니다.
- tryConvert 함수에서 toFahrenheit 함수가 호출되어 섭씨 온도(100)가 화씨 온도로 변환됩니다.
- 변환된 화씨 온도가 상태로 설정되고, useState에 의해 컴포넌트가 다시 리렌더링됩니다.
- TemperatureInput 컴포넌트가 화씨 온도를 표시하고, 이벤트 핸들러는 handleFahrenheitChange 함수를 호출합니다.
- BoilingVerdict 컴포넌트는 섭씨 온도(100)를 전달받아 물이 끓는지 여부를 확인하고 그에 따라 "물이 끓습니다." 또는 "물이 끓지 않습니다." 메시지를 표시합니다.
- 사용자는 변환된 화씨 온도를 "화씨" 입력 필드에서 확인할 수 있습니다.
function card(props){
const {title, backgroundColor, children } = props;
return (
<div
style={{
margin: 8,
padding: 8,
borderRadius: 8,
boxShadow: "0px 0px 4px grey",
backgroundColor: backgroundColor || "white",
}}
>
{title && <h1>{title}</h1>}
{children}
</div>
);
}
export default card;
function card(props){
const {title, backgroundColor, children } = props;
return (
<div
style={{
margin: 8,
padding: 8,
borderRadius: 8,
boxShadow: "0px 0px 4px grey",
backgroundColor: backgroundColor || "white",
}}
>
{title && <h1>{title}</h1>}
{children}
</div>
);
}
export default card;
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import ProfileCard from './chapter_13/ProfileCard';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ProfileCard/>
</React.StrictMode>
);
reportWebVitals();
- ProfileCard 컴포넌트가 렌더링되면 함수 컴포넌트가 호출됩니다.
- ProfileCard 컴포넌트 안에서 <Card> 컴포넌트가 JSX로 사용되었습니다.
- <Card> 컴포넌트에 title prop으로 "Hama"가 전달되었고, backgroundCorlor prop으로 "4ea04e"가 전달되었습니다. (주의: 오타가 있어서 backgroundCorlor를 backgroundColor로 수정해야 합니다.)
- <Card> 컴포넌트에서는 전달받은 props를 비구조화하여 사용합니다. title, backgroundColor, 그리고 children으로 분리합니다.
- <Card> 컴포넌트는 <div> 요소를 반환합니다. 이 <div>은 스타일이 적용된 박스로, margin, padding, borderRadius, boxShadow, 그리고 backgroundColor 스타일이 설정되어 있습니다.
- title이 존재하는 경우, <h1> 요소가 렌더링되어 "Hama"라는 텍스트가 표시됩니다.
- <Card> 컴포넌트의 children으로 전달된 내용이 렌더링되어 "안녕하세요, 물먹는 하마입니다."와 "저는 리액트를 사용해서 개발하고 있습니다."가 텍스트로 표시됩니다.
- 따라서, 최종적으로 화면에는 스타일이 적용된 "Hama"라는 제목과 두 문장이 포함된 하마 프로필 카드가 표시됩니다.
import { useContext } from "react";
import ThemeContext from "./ThemeContext";
function MainContent(props) {
const {theme, toggleTheme} = useContext(ThemeContext);
return (
<div
style={{
width:"100vw",
height:"100vh",
padding:"1.5rem",
backgroundColor: theme == "light" ? "white" : "black",
color: theme == "light" ? "black" : "white",
}}
>
<p>안녕하세요, 테마 변경이 가능한 웹사이트 입니다.</p>
<button onClick={toggleTheme}>테마 변경</button>
</div>
);
}
export default MainContent;
import { useState, useCallback } from "react";
import ThemeContext from "./ThemeContext";
import MainContent from "./MainContent";
function DarkOrLight(props) {
const [theme, setTheme] = useState("light");
const toggleTheme = useCallback(() => {
if (theme === "light"){
setTheme("dark");
}else if (theme === "dark"){
setTheme("light");
}
}, [theme]);
return (
<ThemeContext.Provider value = {{ theme, toggleTheme }}>
<MainContent/>
</ThemeContext.Provider>
);
}
export default DarkOrLight;
import React from "react";
const ThemeContext = React.createContext();
ThemeContext.displayName = "ThemeContext";
export default ThemeContext;
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import reportWebVitals from './reportWebVitals';
import DarkOrLight from './chapter_14/DarkOrLoght';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<DarkOrLight/>
</React.StrictMode>
);
reportWebVitals();
- DarkOrLight 컴포넌트가 렌더링되면 theme 상태와 toggleTheme 함수가 초기값과 함께 생성됩니다. 초기값으로는 "light" 테마가 설정되어 있습니다.
- DarkOrLight 컴포넌트는 ThemeContext.Provider로 감싸져 있습니다. value prop으로는 현재의 theme 상태와 toggleTheme 함수가 제공됩니다.
- MainContent 컴포넌트가 ThemeContext.Provider에 의해 제공된 theme 상태와 toggleTheme 함수를 가져와서 useContext를 통해 사용합니다.
- MainContent 컴포넌트는 <div> 요소를 반환하고, 해당 요소의 스타일은 현재의 theme 값에 따라 동적으로 변경됩니다.
- 만약 theme이 "light"이면, 배경색은 흰색("white"), 글자색은 검정색("black")으로 설정됩니다.
- 만약 theme이 "dark"이면, 배경색은 검정색("black"), 글자색은 흰색("white")으로 설정됩니다.
- <div> 요소 안에는 "안녕하세요, 테마 변경이 가능한 웹사이트 입니다."라는 문장과 "테마 변경" 버튼이 포함되어 있습니다.
- "테마 변경" 버튼을 클릭하면, 해당 버튼에 등록된 onClick 이벤트 핸들러인 toggleTheme 함수가 호출됩니다.
- toggleTheme 함수는 현재의 theme 상태값을 확인하고, "light"이면 "dark"로, "dark"이면 "light"로 변경하여 setTheme을 통해 상태를 갱신합니다.
- setTheme 함수에 의해 theme 상태가 변경되면, DarkOrLight 컴포넌트가 다시 렌더링되어 ThemeContext.Provider가 새로운 theme 값과 toggleTheme 함수를 제공합니다.
- MainContent 컴포넌트는 useContext를 통해 새로운 theme 값과 toggleTheme 함수를 가져오고, 이에 따라 동적으로 변경된 스타일이 반영된 새로운 화면이 렌더링됩니다.
- 이렇게 사용자가 "테마 변경" 버튼을 클릭할 때마다, 테마에 따라 배경색과 글자색이 전환되어 보이는 효과를 가진 테마 변경이 가능한 웹사이트가 만들어집니다.