From 83e8ede27267f3d8efb06abadc4892df3eb0bcab Mon Sep 17 00:00:00 2001 From: dev-owen Date: Fri, 23 Jun 2023 13:54:44 +0900 Subject: [PATCH 1/5] practice/3-b3: starter --- package-lock.json | 10 + package.json | 2 + public/index.html | 1 + public/output.css | 665 ++++++++++++++++++++++++++++++++ src/App.js | 52 ++- src/components/SortableTable.js | 78 ++++ src/components/Table.js | 38 ++ src/index.css | 6 +- tailwind.config.js | 7 + 9 files changed, 844 insertions(+), 15 deletions(-) create mode 100644 public/output.css create mode 100644 src/components/SortableTable.js create mode 100644 src/components/Table.js create mode 100644 tailwind.config.js diff --git a/package-lock.json b/package-lock.json index 02f5862..38d1314 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,9 @@ "@testing-library/user-event": "^12.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", + "react-icons": "^4.10.1", "react-scripts": "^5.0.1", + "tailwindcss": "^3.3.2", "web-vitals": "^0.2.4" } }, @@ -14377,6 +14379,14 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-icons": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.10.1.tgz", + "integrity": "sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", diff --git a/package.json b/package.json index 6c1b63a..996bd57 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "@testing-library/user-event": "^12.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", + "react-icons": "^4.10.1", "react-scripts": "^5.0.1", + "tailwindcss": "^3.3.2", "web-vitals": "^0.2.4" }, "scripts": { diff --git a/public/index.html b/public/index.html index aa069f2..443a0fb 100644 --- a/public/index.html +++ b/public/index.html @@ -5,6 +5,7 @@ + fruit.name, + sortValue: (fruit) => fruit.name, + }, + { + label: '색상', + render: (fruit) =>
, + }, + { + label: '점수', + render: (fruit) => fruit.score, + sortValue: (fruit) => fruit.score, + }, + { + label: '점수의 제곱', + render: (fruit) => fruit.score ** 2, + sortValue: (fruit) => fruit.score ** 2, + }, + ]; + + const keyFn = (fruit) => { + return fruit.name; + }; return ( - - -
- {!ctx.isLoggedIn && } - {ctx.isLoggedIn && } -
-
+
+ +
); } diff --git a/src/components/SortableTable.js b/src/components/SortableTable.js new file mode 100644 index 0000000..2150d57 --- /dev/null +++ b/src/components/SortableTable.js @@ -0,0 +1,78 @@ +import { useState } from 'react'; +import { GoArrowDown, GoArrowUp } from 'react-icons/go'; +import Table from './Table'; + +function SortableTable(props) { + const [sortOrder, setSortOrder] = useState(null); + const [sortBy, setSortBy] = useState(null); + const { config, data } = props; + + const handleClick = (label) => { + // TODO - 정렬 화살표 클릭 시 정렬을 해주는 함수 + }; + + const updatedConfig = config.map((column) => { + if (!column.sortValue) { + return column; + } + + return { + ...column, + header: () => ( + handleClick(column.label)} + > +
+ {getIcons(column.label, sortBy, sortOrder)} + {column.label} +
+ + ), + }; + }); + + let sortedData = data; + if (sortOrder && sortBy) { + const { sortValue } = config.find((column) => column.label === sortBy); + sortedData = [...data].sort((a, b) => { + // TODO - 정렬된 데이터로 바꿔 끼우는 부분 들어갈 comparator 함수 + }); + } + + return ; +} + +function getIcons(label, sortBy, sortOrder) { + if (label !== sortBy) { + return ( +
+ + +
+ ); + } + + if (sortOrder === null) { + return ( +
+ + +
+ ); + } else if (sortOrder === 'asc') { + return ( +
+ +
+ ); + } else if (sortOrder === 'desc') { + return ( +
+ +
+ ); + } +} + +export default SortableTable; diff --git a/src/components/Table.js b/src/components/Table.js new file mode 100644 index 0000000..ca16f2b --- /dev/null +++ b/src/components/Table.js @@ -0,0 +1,38 @@ +import { Fragment } from 'react'; + +function Table({ data, config, keyFn }) { + const renderedHeaders = config.map((column) => { + if (column.header) { + return {column.header()}; + } + + return ; + }); + + const renderedRows = data.map((rowData) => { + const renderedCells = config.map((column) => { + return ( + + ); + }); + + return ( + + {renderedCells} + + ); + }); + + return ( +
{column.label} + {column.render(rowData)} +
+ + {renderedHeaders} + + {renderedRows} +
+ ); +} + +export default Table; diff --git a/src/index.css b/src/index.css index 7fe1477..a2925fb 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,7 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + * { box-sizing: border-box; } @@ -13,4 +17,4 @@ body { main { margin-top: 6rem; -} \ No newline at end of file +} diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..4cf8122 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,7 @@ +module.exports = { + content: ["./src/**/*.{html,js}"], + theme: { + extend: {}, + }, + plugins: [], +} From 7fab3c2603a6645e485197b02c171aaabb2a04a1 Mon Sep 17 00:00:00 2001 From: dev-owen Date: Sun, 25 Jun 2023 02:30:26 +0900 Subject: [PATCH 2/5] feature/4_18: starter --- src/App.js | 46 ++++---------------------- src/components/BackwordCounter.js | 19 +++++++++++ src/components/ForwardCounter.js | 19 +++++++++++ src/components/UI/Card/Card.module.css | 12 +++++-- 4 files changed, 53 insertions(+), 43 deletions(-) create mode 100644 src/components/BackwordCounter.js create mode 100644 src/components/ForwardCounter.js diff --git a/src/App.js b/src/App.js index 44282dc..85fd724 100644 --- a/src/App.js +++ b/src/App.js @@ -1,46 +1,12 @@ import React from 'react'; -import SortableTable from './components/SortableTable'; +import ForwardCounter from './components/ForwardCounter'; +import BackwardCounter from './components/BackwordCounter'; function App() { - const data = [ - { name: '오렌지', color: 'bg-orange-500', score: 5 }, - { name: '사과', color: 'bg-red-500', score: 3 }, - { name: '바나나', color: 'bg-yellow-500', score: 1 }, - { name: '라임', color: 'bg-green-500', score: 4 }, - { name: '체리', color: 'bg-red-700', score: 2.5 }, - ]; - - const config = [ - { - label: '이름', - render: (fruit) => fruit.name, - sortValue: (fruit) => fruit.name, - }, - { - label: '색상', - render: (fruit) =>
, - }, - { - label: '점수', - render: (fruit) => fruit.score, - sortValue: (fruit) => fruit.score, - }, - { - label: '점수의 제곱', - render: (fruit) => fruit.score ** 2, - sortValue: (fruit) => fruit.score ** 2, - }, - ]; - - const keyFn = (fruit) => { - return fruit.name; - }; - - return ( -
- -
- ); + return <> + + + ; } export default App; diff --git a/src/components/BackwordCounter.js b/src/components/BackwordCounter.js new file mode 100644 index 0000000..b6c4360 --- /dev/null +++ b/src/components/BackwordCounter.js @@ -0,0 +1,19 @@ +import { useState, useEffect } from 'react'; +import Card from './UI/Card/Card'; + + +const BackwardCounter = () => { + const [counter, setCounter] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setCounter((prevCounter) => prevCounter - 1); + }, 1000); + + return () => clearInterval(interval); + }, []); + + return {counter}; +}; + +export default BackwardCounter; diff --git a/src/components/ForwardCounter.js b/src/components/ForwardCounter.js new file mode 100644 index 0000000..c6fdae1 --- /dev/null +++ b/src/components/ForwardCounter.js @@ -0,0 +1,19 @@ +import { useState, useEffect } from 'react'; +import Card from './UI/Card/Card'; + + +const ForwardCounter = () => { + const [counter, setCounter] = useState(0); + + useEffect(() => { + const interval = setInterval(() => { + setCounter((prevCounter) => prevCounter + 1); + }, 1000); + + return () => clearInterval(interval); + }, []); + + return {counter}; +}; + +export default ForwardCounter; diff --git a/src/components/UI/Card/Card.module.css b/src/components/UI/Card/Card.module.css index b25bac7..659dfa3 100644 --- a/src/components/UI/Card/Card.module.css +++ b/src/components/UI/Card/Card.module.css @@ -1,5 +1,11 @@ .card { - background: white; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26); - border-radius: 10px; + max-width: 40rem; + margin: 3rem auto; + background-color: white; + padding: 1rem; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); + text-align: center; + font-size: 2.5rem; + font-weight: bold; } From 2efe035e1c52b9ab03629b471d29ad615101cc51 Mon Sep 17 00:00:00 2001 From: dev-owen Date: Sun, 25 Jun 2023 02:52:55 +0900 Subject: [PATCH 3/5] feature/4_19: starter --- src/App.js | 61 +++++++++++++++++++--- src/components/NewTask/NewTask.js | 49 +++++++++++++++++ src/components/NewTask/TaskForm.js | 26 +++++++++ src/components/NewTask/TaskForm.module.css | 18 +++++++ src/components/Tasks/TaskItem.js | 7 +++ src/components/Tasks/TaskItem.module.css | 10 ++++ src/components/Tasks/Tasks.js | 35 +++++++++++++ src/components/Tasks/Tasks.module.css | 10 ++++ src/components/UI/Section.js | 7 +++ src/components/UI/Section.module.css | 8 +++ 10 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 src/components/NewTask/NewTask.js create mode 100644 src/components/NewTask/TaskForm.js create mode 100644 src/components/NewTask/TaskForm.module.css create mode 100644 src/components/Tasks/TaskItem.js create mode 100644 src/components/Tasks/TaskItem.module.css create mode 100644 src/components/Tasks/Tasks.js create mode 100644 src/components/Tasks/Tasks.module.css create mode 100644 src/components/UI/Section.js create mode 100644 src/components/UI/Section.module.css diff --git a/src/App.js b/src/App.js index 85fd724..c223c5d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,12 +1,59 @@ -import React from 'react'; -import ForwardCounter from './components/ForwardCounter'; -import BackwardCounter from './components/BackwordCounter'; +import React, { useEffect, useState } from 'react'; + +import Tasks from './components/Tasks/Tasks'; +import NewTask from './components/NewTask/NewTask'; function App() { - return <> - - - ; + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + const [tasks, setTasks] = useState([]); + + const fetchTasks = async () => { + setIsLoading(true); + setError(null); + try { + const response = await fetch( + 'https://test-owen-f2913-default-rtdb.firebaseio.com//tasks.json' + ); + + if (!response.ok) { + throw new Error('Request failed!'); + } + + const data = await response.json(); + + const loadedTasks = []; + + for (const taskKey in data) { + loadedTasks.push({ id: taskKey, text: data[taskKey].text }); + } + + setTasks(loadedTasks); + } catch (err) { + setError(err.message || 'Something went wrong!'); + } + setIsLoading(false); + }; + + useEffect(() => { + fetchTasks(); + }, []); + + const taskAddHandler = (task) => { + setTasks((prevTasks) => prevTasks.concat(task)); + }; + + return ( + + + + + ); } export default App; diff --git a/src/components/NewTask/NewTask.js b/src/components/NewTask/NewTask.js new file mode 100644 index 0000000..c51a2c1 --- /dev/null +++ b/src/components/NewTask/NewTask.js @@ -0,0 +1,49 @@ +import { useState } from 'react'; + +import Section from '../UI/Section'; +import TaskForm from './TaskForm'; + +const NewTask = (props) => { + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const enterTaskHandler = async (taskText) => { + setIsLoading(true); + setError(null); + try { + const response = await fetch( + 'https://test-owen-f2913-default-rtdb.firebaseio.com/tasks.json', + { + method: 'POST', + body: JSON.stringify({ text: taskText }), + headers: { + 'Content-Type': 'application/json', + }, + } + ); + + if (!response.ok) { + throw new Error('Request failed!'); + } + + const data = await response.json(); + + const generatedId = data.name; // firebase-specific => "name" contains generated id + const createdTask = { id: generatedId, text: taskText }; + + props.onAddTask(createdTask); + } catch (err) { + setError(err.message || 'Something went wrong!'); + } + setIsLoading(false); + }; + + return ( +
+ + {error &&

{error}

} +
+ ); +}; + +export default NewTask; diff --git a/src/components/NewTask/TaskForm.js b/src/components/NewTask/TaskForm.js new file mode 100644 index 0000000..a402962 --- /dev/null +++ b/src/components/NewTask/TaskForm.js @@ -0,0 +1,26 @@ +import { useRef } from 'react'; + +import classes from './TaskForm.module.css'; + +const TaskForm = (props) => { + const taskInputRef = useRef(); + + const submitHandler = (event) => { + event.preventDefault(); + + const enteredValue = taskInputRef.current.value; + + if (enteredValue.trim().length > 0) { + props.onEnterTask(enteredValue); + } + }; + + return ( +
+ + +
+ ); +}; + +export default TaskForm; diff --git a/src/components/NewTask/TaskForm.module.css b/src/components/NewTask/TaskForm.module.css new file mode 100644 index 0000000..3d97724 --- /dev/null +++ b/src/components/NewTask/TaskForm.module.css @@ -0,0 +1,18 @@ +.form { + display: flex; + justify-content: space-between; +} + +.form input { + font:inherit; + padding: 0.25rem; + border: none; + border-bottom: 3px solid #ccc; + flex: 1; + margin-right: 2rem; +} + +.form input:focus { + outline: none; + border-color: #7a0144; +} \ No newline at end of file diff --git a/src/components/Tasks/TaskItem.js b/src/components/Tasks/TaskItem.js new file mode 100644 index 0000000..161a8d7 --- /dev/null +++ b/src/components/Tasks/TaskItem.js @@ -0,0 +1,7 @@ +import classes from './TaskItem.module.css'; + +const TaskItem = (props) => { + return
  • {props.children}
  • +}; + +export default TaskItem; \ No newline at end of file diff --git a/src/components/Tasks/TaskItem.module.css b/src/components/Tasks/TaskItem.module.css new file mode 100644 index 0000000..05947f9 --- /dev/null +++ b/src/components/Tasks/TaskItem.module.css @@ -0,0 +1,10 @@ +.task { + border-bottom: 1px solid #ccc; + padding: 1rem; + font-weight: bold; + font-size: 1.25rem; +} + +.task:last-of-type { + border-bottom: none; +} \ No newline at end of file diff --git a/src/components/Tasks/Tasks.js b/src/components/Tasks/Tasks.js new file mode 100644 index 0000000..dc2e4a0 --- /dev/null +++ b/src/components/Tasks/Tasks.js @@ -0,0 +1,35 @@ +import Section from '../UI/Section'; +import TaskItem from './TaskItem'; +import classes from './Tasks.module.css'; + +const Tasks = (props) => { + let taskList =

    No tasks found. Start adding some!

    ; + + if (props.items.length > 0) { + taskList = ( +
      + {props.items.map((task) => ( + {task.text} + ))} +
    + ); + } + + let content = taskList; + + if (props.error) { + content = ; + } + + if (props.loading) { + content = 'Loading tasks...'; + } + + return ( +
    +
    {content}
    +
    + ); +}; + +export default Tasks; diff --git a/src/components/Tasks/Tasks.module.css b/src/components/Tasks/Tasks.module.css new file mode 100644 index 0000000..6221ad0 --- /dev/null +++ b/src/components/Tasks/Tasks.module.css @@ -0,0 +1,10 @@ +.container { + text-align: center; +} + +.container ul { + list-style: none; + margin: 0; + padding: 0; + text-align: left; +} diff --git a/src/components/UI/Section.js b/src/components/UI/Section.js new file mode 100644 index 0000000..4dac8ff --- /dev/null +++ b/src/components/UI/Section.js @@ -0,0 +1,7 @@ +import classes from './Section.module.css'; + +const Section = (props) => { + return
    {props.children}
    ; +}; + +export default Section; diff --git a/src/components/UI/Section.module.css b/src/components/UI/Section.module.css new file mode 100644 index 0000000..33281d7 --- /dev/null +++ b/src/components/UI/Section.module.css @@ -0,0 +1,8 @@ +.section { + max-width: 40rem; + margin: 2rem auto; + background-color: white; + padding: 1rem; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25); +} From c690ed76214281c74d952da43b39bb0d96bc2a3d Mon Sep 17 00:00:00 2001 From: dev-owen Date: Mon, 26 Jun 2023 21:58:48 +0900 Subject: [PATCH 4/5] fix: text edit --- src/components/NewTask/TaskForm.js | 32 +++++++++---------- src/components/Tasks/Tasks.js | 50 +++++++++++++++--------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/components/NewTask/TaskForm.js b/src/components/NewTask/TaskForm.js index a402962..54f5dcf 100644 --- a/src/components/NewTask/TaskForm.js +++ b/src/components/NewTask/TaskForm.js @@ -1,26 +1,26 @@ -import { useRef } from 'react'; +import { useRef } from "react"; -import classes from './TaskForm.module.css'; +import classes from "./TaskForm.module.css"; const TaskForm = (props) => { - const taskInputRef = useRef(); + const taskInputRef = useRef(); - const submitHandler = (event) => { - event.preventDefault(); + const submitHandler = (event) => { + event.preventDefault(); - const enteredValue = taskInputRef.current.value; + const enteredValue = taskInputRef.current.value; - if (enteredValue.trim().length > 0) { - props.onEnterTask(enteredValue); - } - }; + if (enteredValue.trim().length > 0) { + props.onEnterTask(enteredValue); + } + }; - return ( -
    - - -
    - ); + return ( +
    + + +
    + ); }; export default TaskForm; diff --git a/src/components/Tasks/Tasks.js b/src/components/Tasks/Tasks.js index dc2e4a0..abec27c 100644 --- a/src/components/Tasks/Tasks.js +++ b/src/components/Tasks/Tasks.js @@ -1,35 +1,35 @@ -import Section from '../UI/Section'; -import TaskItem from './TaskItem'; -import classes from './Tasks.module.css'; +import Section from "../UI/Section"; +import TaskItem from "./TaskItem"; +import classes from "./Tasks.module.css"; const Tasks = (props) => { - let taskList =

    No tasks found. Start adding some!

    ; + let taskList =

    태스크가 없습니다. 추가해주세요.

    ; - if (props.items.length > 0) { - taskList = ( -
      - {props.items.map((task) => ( - {task.text} - ))} -
    - ); - } + if (props.items.length > 0) { + taskList = ( +
      + {props.items.map((task) => ( + {task.text} + ))} +
    + ); + } - let content = taskList; + let content = taskList; - if (props.error) { - content = ; - } + if (props.error) { + content = ; + } - if (props.loading) { - content = 'Loading tasks...'; - } + if (props.loading) { + content = "태스크 로딩중..."; + } - return ( -
    -
    {content}
    -
    - ); + return ( +
    +
    {content}
    +
    + ); }; export default Tasks; From 1eb69de601e37320366c3ef9ac4603a3f59af111 Mon Sep 17 00:00:00 2001 From: mangwoncassie Date: Fri, 22 Dec 2023 14:01:58 +0900 Subject: [PATCH 5/5] feat: api fetching is done --- package-lock.json | 171 ++++++++----------------------- package.json | 2 +- src/components/NewsList/index.js | 21 +++- 3 files changed, 62 insertions(+), 132 deletions(-) diff --git a/package-lock.json b/package-lock.json index f13c2be..78157aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "react": "^18.0.0", "react-dom": "^18.0.0", "react-scripts": "^5.0.1", - "styled-components": "^6.0.0-rc.3", + "styled-components": "^6.1.2", "web-vitals": "^0.2.4" } }, @@ -46,78 +46,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/cli": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.5.tgz", - "integrity": "sha512-N5d7MjzwsQ2wppwjhrsicVDhJSqF9labEP/swYiHhio4Ca2XjEehpgPmerjnLQl7BPE59BLud0PTWGYwqFl/cQ==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "commander": "^4.0.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.2.0", - "make-dir": "^2.1.0", - "slash": "^2.0.0" - }, - "bin": { - "babel": "bin/babel.js", - "babel-external-helpers": "bin/babel-external-helpers.js" - }, - "engines": { - "node": ">=6.9.0" - }, - "optionalDependencies": { - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", - "chokidar": "^3.4.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/cli/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@babel/cli/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/cli/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/cli/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/cli/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "engines": { - "node": ">=6" - } - }, "node_modules/@babel/code-frame": { "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", @@ -608,20 +536,6 @@ "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-external-helpers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.22.5.tgz", - "integrity": "sha512-ngnNEWxmykPk82mH4ajZT0qTztr3Je6hrMuKAslZVM8G1YZTENJSYwrIGtt6KOtznug3exmAtF4so/nPqJuA4A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-proposal-async-generator-functions": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", @@ -2236,6 +2150,19 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, "node_modules/@emotion/unitless": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", @@ -3108,12 +3035,6 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, - "node_modules/@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.3", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", - "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", - "optional": true - }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -4397,6 +4318,11 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.5", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", @@ -6584,6 +6510,11 @@ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -8493,11 +8424,6 @@ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" }, - "node_modules/fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -12288,9 +12214,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -12938,9 +12864,9 @@ } }, "node_modules/postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "funding": [ { "type": "opencollective", @@ -12956,7 +12882,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -15722,25 +15648,18 @@ } }, "node_modules/styled-components": { - "version": "6.0.0-rc.3", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.0.0-rc.3.tgz", - "integrity": "sha512-5FbCTxynopck99GRwM5Ey0+VRp8pkQq69TwGOJJeYtR7gPvwGjNx8yBPLN7/dfxwwvn9ymOZYB19eQkv2k70wQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.2.tgz", + "integrity": "sha512-LJjirciivbOKNuKKjheXMeNOlFspur4s2/AYW2hPyrL4RhwEFiowF9axgjeMVxX7siEoLJAitKrzpuNApJ5R/Q==", "dependencies": { - "@babel/cli": "^7.21.0", - "@babel/core": "^7.21.0", - "@babel/helper-module-imports": "^7.18.6", - "@babel/plugin-external-helpers": "^7.18.6", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.7", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@babel/traverse": "^7.21.2", + "@emotion/is-prop-valid": "^1.2.1", "@emotion/unitless": "^0.8.0", + "@types/stylis": "^4.0.2", "css-to-react-native": "^3.2.0", - "postcss": "^8.4.23", + "csstype": "^3.1.2", + "postcss": "^8.4.31", "shallowequal": "^1.1.0", - "stylis": "^4.2.0", + "stylis": "^4.3.0", "tslib": "^2.5.0" }, "engines": { @@ -15751,14 +15670,8 @@ "url": "https://opencollective.com/styled-components" }, "peerDependencies": { - "babel-plugin-styled-components": ">= 2", "react": ">= 16.8.0", "react-dom": ">= 16.8.0" - }, - "peerDependenciesMeta": { - "babel-plugin-styled-components": { - "optional": true - } } }, "node_modules/stylehacks": { @@ -15777,9 +15690,9 @@ } }, "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" }, "node_modules/sucrase": { "version": "3.32.0", diff --git a/package.json b/package.json index 9d8ee7b..3be8fce 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "react": "^18.0.0", "react-dom": "^18.0.0", "react-scripts": "^5.0.1", - "styled-components": "^6.0.0-rc.3", + "styled-components": "^6.1.2", "web-vitals": "^0.2.4" }, "scripts": { diff --git a/src/components/NewsList/index.js b/src/components/NewsList/index.js index d5c126b..1ffbf39 100644 --- a/src/components/NewsList/index.js +++ b/src/components/NewsList/index.js @@ -1,8 +1,25 @@ -import React from 'react'; +import { useEffect, useState } from 'react'; import NewsItem from '../NewsItem'; const NewsList = () => { + const [news, setNews] = useState([]); + + useEffect(()=>{ + getNewsList(); + }, []); + + const getNewsList = () => { + fetch('https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=06b21f71f1714078af2c68958a1dbcd5').then((response) => response.json()) + .then((data) => { + console.log(data); + setNews(data.articles) + }) + } + + //무한루프 원인 getNewsList(); + + const dummy = [ { "source": { @@ -46,7 +63,7 @@ const NewsList = () => { ] return (
    - {dummy.map(news => )} + {news.map(news => )}
    ); };