Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions my-app/src/chapter_08/ConfirmButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

function ConfirmButton(props) {
const [isConfirmed, setIsConfirmed] = React.useState(false);

const handleConfirm = () => {
setIsConfirmed(prevIsConfirmed => !prevIsConfirmed);
};

return (
<button
onClick={handleConfirm}
disabled={isConfirmed}
>
{isConfirmed ? "확인됨" : "확인하기"}
</button>
);
}

export default ConfirmButton;
27 changes: 27 additions & 0 deletions my-app/src/chapter_09/LandingPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useState } from "react";
import Toolbar from "./Toolbar";

function LandingPage(props) {
const [isLoggedIn, setIsLoggedIn] = useState(false);

const onClickLogin = () => {
setIsLoggedIn(true);
};

const onClickLogout = () => {
setIsLoggedIn(false);
};

return (
<div>
<Toolbar
isLoggedIn={isLoggedIn}
onClickLogin={onClickLogin}
onClickLogout={onClickLogout}
/>
<div style={{ padding: 16 }}>리액트 공부!</div>
</div>
);
}

export default LandingPage;
30 changes: 30 additions & 0 deletions my-app/src/chapter_09/Toolbar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";

const styles = {
wrapper: {
display: "flex",
padding: 16,
flexDirection: "row",
borderBottom: "1px solid grey",
},
greeting: {
marginRight: 8,
},
};

function Toolbar(props) {
const { isLoggedIn, onClickLogin, onClickLogout } = props;

return (
<div style={styles.wrapper}>
{isLoggedIn && <span style={styles.greeting}>환영합니다!</span>}
{isLoggedIn ? (
<button onClick={onClickLogout}>로그아웃</button>
) : (
<button onClick={onClickLogin}>로그인</button>
)}
</div>
);
}

export default Toolbar;
34 changes: 34 additions & 0 deletions my-app/src/chapter_10/AttendanceBook.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";

const students = [
{
id: 1,
name: "Inje",
},
{
id: 2,
name: "Jisoo",
},
{
id: 3,
name: "Jiwon",
},
{
id: 4,
name: "Soojin",
},
];

function AttendanceBook(props) {
return (
<ul>
{students.map((student, index) => {
return <li key={index}> {student.name}
</li>;
})}
</ul>

)
}

export default AttendanceBook;
37 changes: 37 additions & 0 deletions my-app/src/chapter_11/SignUp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, {useState} from "react";

function SignUp(props) {
const [name, setName] = useState("");
const [gender, setGender] = useState("남자");

const handleChangeName = (e) => {
setName(e.target.value);
};
const handleChangeGender = (e) => {
setGender(e.target.value);
};

const handleSubmit = (e) => {
alert(`이름: ${name}, 성별: ${gender}`);
e.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>
</select>
</label>
<button type="submit">제출</button>
</form>
);
}
export default SignUp;
65 changes: 65 additions & 0 deletions my-app/src/chapter_12/Calculator.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
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, convert) {
const input = parseFloat(temperature);
if (Number.isNaN(input)) {
return "";
}
const output = convert(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
scale="f"
temperature={fahrenheit}
onTemperatureChange={handleFahrenheitChange}
/>
<BoilingVerdict celsius={parseFloat(celsius)} />
</div>
);
}

export default Calculator;
21 changes: 21 additions & 0 deletions my-app/src/chapter_12/TemperatureInput.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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} />
</fieldset>
);
}

export default TemperatureInput;
20 changes: 20 additions & 0 deletions my-app/src/chapter_13/Card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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;
12 changes: 12 additions & 0 deletions my-app/src/chapter_13/ProfileCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Card from "./Card";

function ProfileCard(props) {
return (
<Card title="Kim Yunji" backgroundColor="#4ea04e">
<p>안녕하세요, 김윤지입니다.</p>
<p>저는 리액트를 사용해서 개발하고 있습니다.</p>
</Card>
);
}

export default ProfileCard;
8 changes: 7 additions & 1 deletion my-app/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ import Clock from './chapter_04/Clock';
import CommentList from './chapter_05/CommentList';
import NotificationList from './chapter_06/NotificationList';
import Accommodate from './chapter_07/Accommodate';
import ConfirmButton from './chapter_08/ConfirmButton';
import LandingPage from './chapter_09/LandingPage';
import AttendanceBook from './chapter_10/AttendanceBook';
import SignUp from './chapter_11/SignUp';
import Calculator from './chapter_12/Calculator';
import ProfileCard from './chapter_13/ProfileCard';

const root = ReactDOM.createRoot(document.getElementById('root')); // React 18 방식

root.render(
<React.StrictMode>
<Accommodate />
<ProfileCard />
</React.StrictMode>
);

Expand Down