Skip to content
Merged
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
36 changes: 36 additions & 0 deletions jeongmin/codes/test-app/src/assignment/week3/Todo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useRef } from "react";

export default function Todo({ title, text, deleteTodo }) {
const toEraseTitle = useRef(null);

return (
<div
style={{
width: "100%",
border: "1px solid black",
borderRadius: "10px",
padding: "5px 10px",
boxSizing: "border-box",
display: "flex",
justifyContent: "space-between",
}}
>
<div>
<div
style={{ color: "skyblue" }}
ref={toEraseTitle}
>
{title}
</div>
<div>{text}</div>
</div>
<button
onClick={(e) => {
deleteTodo(toEraseTitle.current.textContent);
}}
>
완료
</button>
</div>
);
}
64 changes: 64 additions & 0 deletions jeongmin/codes/test-app/src/assignment/week3/TodoList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { useState } from "react";
import useTodo from "./useTodo";
import Todo from "./Todo";

export default function TodoList() {
const [titleInput, setTitleInput] = useState("");
const [textInput, setTextInput] = useState("");
const [todo, addTodo, deleteTodo] = useTodo([]);
return (
<div
style={{
height: "100vh",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
padding: "5px 10px",
boxSizing: "border-box",
}}
>
<div>
{todo.map((td, i) => (
<Todo
key={i}
title={td.title}
text={td.text}
deleteTodo={deleteTodo} // prop으로 내려줌
/>
))}
</div>

<div
style={{
display: "flex",
flexDirection: "column",
}}
>
<input
placeholder="투두 타이틀 입력"
style={{ width: "50%" }}
value={titleInput}
onChange={(e) => {
setTitleInput(e.target.value);
}}
/>
<textarea
placeholder="투두 내용 입력"
style={{ height: "5rem" }}
value={textInput}
onChange={(e) => {
setTextInput(e.target.value);
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
addTodo(titleInput, textInput);
setTitleInput("");
setTextInput("");
}
}}
/>
</div>
</div>
);
}
12 changes: 12 additions & 0 deletions jeongmin/codes/test-app/src/assignment/week3/useTodo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { useState } from "react";

export default function useTodo(td) {
const [todo, setTodo] = useState(td);
const addTodo = (title, text) => {
setTodo((prev) => [...prev, { title, text }]);
}
const deleteTodo = (title) => {
setTodo((prev) => prev.filter((todo) => todo.title !== title));
};
return [todo, addTodo, deleteTodo];
}
42 changes: 42 additions & 0 deletions jeongmin/codes/test-app/src/chapter_06/Notification.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";

const styles = {
wrapper: {
margin: 8,
padding: 8,
display: "flex",
flexDirection: "row",
border: "1px solid grey",
borderRadius: 16,
},
};

class Notification extends React. Component {
constructor(props) {
super(props);

this.state = {};
}

componentDidMount() {
console.log(`${this.props.id} componentDidMount() called.`);
}

componentDidUpdate() {
console.log(`${this.props.id} componentDidUpdate() called.`);
}

componentWillUnmount() {
console.log(`${this.props.id} componentWillUnmount() called.`);
}

render() {
return (
<div style={styles.wrapper}>
<span style={styles.messageText}>{this.props.message}</span>
</div>
);
}
}

export default Notification;
68 changes: 68 additions & 0 deletions jeongmin/codes/test-app/src/chapter_06/NotificationList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from "react";
import Notification from "./Notification";

const reservedNotifications = [
{
id: 1,
message: "안녕하세요, 오늘 일정을 알려드립니다.",
},
{
id: 2,
message: "점심식사 시간입니다.",
},
{
id: 3,
message: "이제 곧 미팅이 시작됩니다.",
}
];

var timer;

class NotificationList extends React.Component {
constructor(props) {
super(props);

// 사용할 데이터를 state에 넣어 초기화 함
this.state = {
notifications: [],
};
}

componentDidMount() {
const { notifications } = this.state;
timer = setInterval(() => {
if (notifications.length < reservedNotifications.length) {
const index = notifications.length;
notifications.push(reservedNotifications[index]);

// state 업데이트
this.setState({
notifications: notifications,
});
} else {
this.setState({
notifications: [],
});
clearInterval(timer);
}
}, 1000);
}

render() {
return (
<div>
{this.state.notifications.map((notification) => {
return (
<Notification
key={notification.id}
id={notification.id}
message={notification.message}
/>
);
})}
</div>
);
}
}

export default NotificationList;
36 changes: 36 additions & 0 deletions jeongmin/codes/test-app/src/chapter_07/Accommodate.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useState, useEffect } from "react";
import useCounter from "./useCounter";
import { isLabelWithInternallyDisabledControl } from "@testing-library/user-event/dist/utils";

const MAX_CAPACITY = 10;

function Accommodate(props) {
const [isFull, setIsFull] = useState(false);
const [count, increaseCount, decreaseCount] = useCounter(0);

useEffect(() => {
console.log("======================")
console.log("useEffect() is called.");
console.log(`isFull: ${isFull}`);
});

useEffect(() => {
setIsFull(count >= MAX_CAPACITY);
console.log(`Current count value: ${count}`);
}, [count]);

return (
<div style={{ padding: 16 }}>
<p>{`총 ${count}명 수용했습니다.`}</p>

<button onClick={increaseCount} disabled={isFull}>
입장
</button>
<button onClick={decreaseCount}>퇴장</button>

{isFull && <p style={{ color: "red" }}>정원이 가득찼습니다.</p>}
</div>
);
}

export default Accommodate;
12 changes: 12 additions & 0 deletions jeongmin/codes/test-app/src/chapter_07/useCounter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";

function useCounter(initialValue) {
const [count, setCount] = useState(initialValue);

const increaseCount = () => setCount((count) => count +1);
const decreaseCount = () => setCount((count) => Math.max(count - 1, 0));

return [count, increaseCount, decreaseCount];
}

export default useCounter;
11 changes: 6 additions & 5 deletions jeongmin/codes/test-app/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import reportWebVitals from './reportWebVitals';
import Library from './chapter_03/Library';
import Clock from './chapter_04/Clock';
import CommentList from './chapter_05/CommentList';
import Notification from './chapter_06/Notification';
import NotificationList from './chapter_06/NotificationList';
import Accommodate from './chapter_07/Accommodate';

const container = document.getElementById('root');
const root = createRoot(container);

const root = createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<CommentList />
<Accommodate />
</React.StrictMode>
);

reportWebVitals();
reportWebVitals();
3 changes: 3 additions & 0 deletions jeongmin/notes/week3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
티스토리 링크

https://joanne15433.tistory.com/3