Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

news-viewer project finished. code review start #42

Merged
merged 1 commit into from
Nov 16, 2020
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.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
1 change: 1 addition & 0 deletions myCode/news-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"axios": "^0.21.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.0",
"styled-components": "^5.2.1",
"web-vitals": "^0.2.4"
Expand Down
24 changes: 6 additions & 18 deletions myCode/news-viewer/src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import React, {useState} from 'react'
import axios from 'axios'

import React from 'react'
import {Route} from 'react-router-dom'
import NewsPage from './components/NewsPage'
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

컴포넌트 파일에서 만들어진 News page 값을 React-Router로 연결해 값을 받는다.

const App = ()=>{
const [data, setData] = useState(null)
const onClick = async ()=>{
try{
const response = await axios.get('https://newsapi.org/v2/top-headlines?country=kr&apiKey=')
setData(response.data)
}catch(e){
console.log(e)
}
}

return (
<div>
<div>
<button onClick={onClick}>Loading</button>
</div>
{data && <textarea rows={7} value={JSON.stringify(data, null, 2)} readOnly={true} />}
</div>
<Route path="/:category?" component={NewsPage} />
)

}

export default App
92 changes: 92 additions & 0 deletions myCode/news-viewer/src/components/Categories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from 'react'
import styled from 'styled-components'
import {NavLink} from 'react-router-dom'

const categories = [
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NavLink (React Router) 에서 상단 네브바를 구성할 리터럴 객체 작업

{
name : "all",
text : "see all"
},
{
name : "business",
text : "Business"
},
{
name : "entertainment",
text : "entertainment"
},
{
name : "health",
text : "health"
},
{
name : "science",
text : "science"
},
{
name : "sports",
text : "sports"
},
{
name : "technology",
text : "technology"
}
]

const CategoriesBlock = styled.div`

display:flex;
padding: 1rem;
width: 768px;
margin: 0 auto;
@media screen and (max-width:768px){
width: 100%;
overflow-x:auto;
}
`;

const Category = styled(NavLink)`

font-size : 1.125rem;
cursor: pointer;
white-space : pre;
text-decoration : none;
color : inherit;
padding-bottom : 0.25rem;

&:hover {
color : #495057;
}

&.active {
font-weight : 600;
border-bottom : 2px solid #22b8cf;
color: #22b8cf;
&:hover {
color : #3bc9db;
}
}

&+&{
margin-left : 1rem;
}
`;

const Categories = ()=>{
return (
<CategoriesBlock>
{categories.map(c=>(
<Category
key={c.name}
activeClassName="active"
exact={c.name==='all'}
to={c.name === 'all' ? '/' : `/${c.name}`}
>
{c.text}
</Category>
))}
</CategoriesBlock>
)
}

export default Categories;
16 changes: 8 additions & 8 deletions myCode/news-viewer/src/components/NewsItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@ display : flex;
width : 160px;
height : 100px;
object-fit : cover;
}
}
};
};
.contents{
h2{
margin:0;
a{
color:black;
}
}
};
};
p{
margin: 0;
line-height: 1.5;
margin-top: 0.5 rem;
wihte-space: normal;
}
}
};
};
& + & {
margin-top : 3rem;
}
`
};
`;

const NewsItem = ({article})=>{
const {title, description, url, urlToImage} = article
Expand Down
61 changes: 61 additions & 0 deletions myCode/news-viewer/src/components/NewsList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, {useEffect, useState} from 'react'
import styled from 'styled-components'
import NewsItem from './NewsItem'
import axios from 'axios'
import usePromise from '../lib/usePromise'


const NewsListBlock = styled.div`
box-sizing: border-box;
padding-bottom : 3rem;
width : 768px;
margin : 0 auto;
margin-top : 2rem;
@media screen and (max-width: 768px){
width: 100%;
padding-left : 1rem;
padding-right : 1rem;
}
`;

const NewsList = ({category})=>{
// const [article, setArticle] = useState(null)
// const [loading, setLoading] = useState(false)
// useEffect(()=>{
// const fetchData = async ()=>{
// setLoading(true)
// try{
// const query = category === 'all' ? '' : `&category=${category}`
// const response = await axios.get(`https://newsapi.org/v2/top-headlines?country=kr${query}&apiKey=b893fb160a4b401fb4974a5a89d42111`)
// setArticle(response.data.articles)
// }catch(e){
// console.log(e)
// }
// setLoading(false)
// }
// fetchData()
const [loading, response, error] = usePromise(()=>{
const query = category === 'all' ? '' : `&category=${category}`
return axios.get(`https://newsapi.org/v2/top-headlines?country=kr${query}&apiKey=b893fb160a4b401fb4974a5a89d42111`)
}, [category])

if(loading){
return <NewsListBlock>Loading ...</NewsListBlock>
}
if(!response){
return null
}
if(error){
return <NewsListBlock>Error Occured!</NewsListBlock>
}
const {articles} = response.data
return (
<NewsListBlock>
{articles.map(article=>(
<NewsItem key={article.key} article={article} />
))}
</NewsListBlock>
)
}

export default NewsList
15 changes: 15 additions & 0 deletions myCode/news-viewer/src/components/NewsPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'
import Categories from '../components/Categories'
import NewsList from '../components/NewsList'

const NewsPage = ({match}) =>{
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{match} 속성은 React-Router를 활용하면 가져오는 속성으로 url의 param을 가져온다.

const category = match.params.category || 'all'
return (
<>
<Categories />
<NewsList category={category}/>
</>
)
}

export default NewsPage;
5 changes: 3 additions & 2 deletions myCode/news-viewer/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {BrowserRouter} from 'react-router-dom'
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react-router-dom 설정하기


ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</React.StrictMode>,
</BrowserRouter>,
document.getElementById('root')
);

Expand Down
24 changes: 24 additions & 0 deletions myCode/news-viewer/src/lib/usePromise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {useState, useEffect} from 'react'

export default function usePromise(promiseCreator, deps){
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

news api 정보의 대기, 로딩 완료, 실패를 가져오게끔 별도의 컴포넌트를 구성해 작업하는 파일

// standby / completed / fail status management
const [loading, setLoading] = useState(false)
const [resolved, setResolved] = useState(null)
const [error, setError] = useState(null)

useEffect(()=>{
const process = async () =>{
setLoading(true)
try{
const resolved = await promiseCreator()
setResolved(resolved)
}catch(e){
setError(e)
}
setLoading(false)
}
process()
},
deps)
return [loading, resolved, error]
}