Sidebar 컴포넌트 기술 요구사항
- App 컴포넌트의 후손 컴포넌트로 Sidebar 컴포넌트가 있어야 합니다.
- Font Awesome을 활용하여 트윗 메시지 아이콘이 있어야 합니다. (className : "far fa-comment-dots")
1. App 컴포넌트의 후손컴포넌트로 Silderbar 컴포넌트가 있어야 합니다.
const App = () => {
return (
<div className="App">
<main>
{/* TODO : Sidebar 컴포넌트를 작성합니다. */}
<Sidebar />
<Features />
</main>
</div>
);
};
컴포넌트란? 프로그래밍에 있어 재사용이 가능한 각각의 독립된 모듈을 뜻 합니다.
컴포넌트이므로 className 을 지정할때 첫글자를 대문자로! 해줍니다.
소문자로 시작하게 되면 일반적인 HTML엘리먼트로 인식
className?
class로 작성하게 된다면 React에서는 이를 html 클래스 속성 대신 자바스크립트 클래스로 받아들이기 때문 입니다.
2. Font Awesome을 활용하여 트윗 메시지 아이콘이 있어야 합니다. (className : "far fa-comment-dots")
const Sidebar = () => {
return (
<section className="sidebar">
{/* TODO : 메세지 아이콘을 작성합니다. */}
<i className='far fa-comment-dots'></i>
</section>
);
};
Font Awesome을 활용 할 때 접두사가 붙는 아이콘 이름 fa- , 아이콘 이름 클래스<i> 를 줍니다.
자세한 내용은 https://fontawesome.com/docs/web/add-icons/how-to 여기를 참고하시면 좋습니다!
Counter 컴포넌트 기술 요구사항
- Feature 컴포넌트의 후손 컴포넌트로 Counter 컴포넌트가 있어야 합니다.
- dummyTweet로 전달되는 트윗 개수와 카운트가 일치해야 합니다. ex) total : 5
- total과 숫자가 콘텐츠에 포함되어 있어야 합니다
1. Feature 컴포넌트의 후손 컴포넌트로 Counter 컴포넌트가 있어야 합니다.
const Features = () => {
return (
<section className="features">
<div className="tweetForm__container">
<div className="tweetForm__wrapper">
<div className="tweetForm__profile"></div>
<Counter />
</div>
</div>
<Tweets />
<Footer />
</section>
);
};
2. dummyTweet로 전달되는 트윗 개수와 카운트가 일치해야 합니다. ex) total : 5
일단 dummyTweet 데이터 는 dummyData.js에 있으므로 dummyData.js를 확인해줍니다.
dummyData.js
// 테스트용 더미 데이터로 수정하지 않습니다.
const getRandomNumber = (min, max) => {
return parseInt(Math.random() * (Number(max) - Number(min) + 2));
};
const getParsedDate = (createdAt) => {
return new Date(createdAt).toLocaleDateString('ko-KR');
};
export const dummyTweets = [
{
id: 1,
username: 'kimcoding',
picture: `https://randomuser.me/api/portraits/women/${getRandomNumber(
1,
98
)}.jpg`,
content:
'모든 국민은 인간으로서의 존엄과 가치를 가지며, 행복을 추구할 권리를 가진다. 모든 국민은 종교의 자유를 가진다. 국가는 농·어민과 중소기업의 자조조직을 육성하여야 하며, 그 자율적 활동과 발전을 보장한다. 모든 국민은 양심의 자유를 가진다. 누구든지 체포 또는 구속을 당한 때에는 즉시 변호인의 조력을 받을 권리를 가진다.',
createdAt: getParsedDate('2022-02-24T16:17:47.000Z'),
updatedAt: getParsedDate('2022-02-24T16:17:47.000Z'),
},
{
id: 2,
username: 'parkhacker',
picture: `https://randomuser.me/api/portraits/men/${getRandomNumber(
1,
98
)}.jpg`,
content:
'형사피고인은 유죄의 판결이 확정될 때까지는 무죄로 추정된다. 모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며, 동일한 범죄에 대하여 거듭 처벌받지 아니한다. 모든 국민은 행위시의 법률에 의하여 범죄를 구성하지 아니하는 행위로 소추되지 아니하며, 동일한 범죄에 대하여 거듭 처벌받지 아니한다. 모든 국민은 고문을 받지 아니하며, 형사상 자기에게 불리한 진술을 강요당하지 아니한다.',
createdAt: getParsedDate('2022-02-25T16:17:47.000Z'),
updatedAt: getParsedDate('2022-02-25T16:17:47.000Z'),
},
{
id: 3,
username: 'leedesign',
picture: `https://randomuser.me/api/portraits/women/${getRandomNumber(
1,
98
)}.jpg`,
content:
'모든 국민은 고문을 받지 아니하며, 형사상 자기에게 불리한 진술을 강요당하지 아니한다. 모든 국민은 양심의 자유를 가진다. 모든 국민은 사생활의 비밀과 자유를 침해받지 아니한다. 연소자의 근로는 특별한 보호를 받는다. 형사피고인이 스스로 변호인을 구할 수 없을 때에는 법률이 정하는 바에 의하여 국가가 변호인을 붙인다.',
createdAt: getParsedDate('2022-02-26T16:17:47.000Z'),
updatedAt: getParsedDate('2022-02-26T16:17:47.000Z'),
},
{
id: 4,
username: 'songfront',
picture: `https://randomuser.me/api/portraits/men/${getRandomNumber(
1,
98
)}.jpg`,
content:
'형사피고인은 상당한 이유가 없는 한 지체없이 공개재판을 받을 권리를 가진다. 공무원은 국민전체에 대한 봉사자이며, 국민에 대하여 책임을 진다. 모든 국민은 고문을 받지 아니하며, 형사상 자기에게 불리한 진술을 강요당하지 아니한다. 누구든지 체포 또는 구속을 당한 때에는 적부의 심사를 법원에 청구할 권리를 가진다. 대한민국의 경제질서는 개인과 기업의 경제상의 자유와 창의를 존중함을 기본으로 한다.',
createdAt: getParsedDate('2022-02-27T16:17:47.000Z'),
updatedAt: getParsedDate('2022-02-27T16:17:47.000Z'),
},
{
id: 5,
username: 'choiback',
picture: `https://randomuser.me/api/portraits/women/${getRandomNumber(
1,
98
)}.jpg`,
content:
'주거에 대한 압수나 수색을 할 때에는 검사의 신청에 의하여 법관이 발부한 영장을 제시하여야 한다. 대한민국은 국제평화의 유지에 노력하고 침략적 전쟁을 부인한다. 국가유공자·상이군경 및 전몰군경의 유가족은 법률이 정하는 바에 의하여 우선적으로 근로의 기회를 부여받는다. 여자의 근로는 특별한 보호를 받으며, 고용·임금 및 근로조건에 있어서 부당한 차별을 받지 아니한다. 모든 국민은 주거의 자유를 침해받지 아니한다.',
createdAt: getParsedDate('2022-02-28T16:17:47.000Z'),
updatedAt: getParsedDate('2022-02-28T16:17:47.000Z'),
},
];
코드를 확인하면 dummyTweets 라는 변수에 5개의 데이터가 있는걸 확인 할수 있습니다.
그러므로 dummyTweets.length(길이)를 이용해줍니다. + ex) total : 이것도 표현 해줘야 하기 때문에
{'total:' + dummyTweets.length} 가 됩니다.
const Counter = () => {
return (
<div className="tweetForm__input">
<div className="tweetForm__inputWrapper">
<div className="tweetForm__count" role="status">
{/* TODO : dummyTweet로 전달되는 데이터의 갯수를 보여줍니다. 데이터는 총 5개 */}
{'total:' + dummyTweets.length}
</div>
</div>
</div>
);
};
Footer 컴포넌트 기술 요구사항
- Features 컴포넌트의 후손 컴포넌트로 Footer 컴포넌트가 있어야 합니다.
- Footer 컴포넌트의 후손 엘리먼트로 시맨틱 엘리먼트 footer가 있어야 합니다.
- 시멘틱 엘리먼트 <footer>가 포함되어야 합니다.
1. Features 컴포넌트의 후손 컴포넌트로 Footer 컴포넌트가 있어야 합니다.
const Features = () => {
return (
<section className="features">
<div className="tweetForm__container">
<div className="tweetForm__wrapper">
<div className="tweetForm__profile"></div>
<Counter />
</div>
</div>
<Tweets />
<Footer />
</section>
);
};
2. Footer 컴포넌트의 후손 엘리먼트로 시맨틱 엘리먼트 footer가 있어야 합니다.
const Footer = () => {
return (
<div>
<footer>
{/* <img id="logo" src={`${process.env.PUBLIC_URL}/codestates-logo.png`} /> */}
Copyright @ 2022 Code States
</footer>
</div>
);
};
시맨틱 엘리먼트(요소)?
시맨틱하다 - 의미를 가진다는 것 입니다.
브라우저와 개발자 모두에게 그 의미를 명확하게 설명합니다. ex)<h1></h1> , <header></header>, <footer></footer>...
Tweets 컴포넌트 기술 요구사항
- 트윗 저자의 프로필 사진이 있어야 합니다.
- li.tweet 엘리먼트의 후손 엘리먼트로 <img> 엘리먼트를 생성하고 dummyTweets의 이미지 주소 정보를 찾아서 <src> 속성을 지정합니다.
- 유저 이름이 있어야 합니다.
- li.tweet 엘리먼트의 후손 엘리먼트로 <span> 엘리먼트를 생성하고 dummyTweets의 유저 이름을 <span>의 텍스트 콘텐츠로 넣습니다.
- 클래스 이름은 tweet__username으로 지정합니다.
- 트윗 생성 일자(yyyy. m. d.) 가 있어야 합니다.
- li.tweet 엘리먼트의 후손 엘리먼트로 <span> 엘리먼트를 생성하고 dummyTweets의 트윗 생성 일자를 <span>의 텍스트 콘텐츠로 넣습니다.
- 클래스 이름은 tweet__createdAt으로 지정합니다.
- 트윗 생성 일자는 yyyy. m. d. 형식으로 표시되어야 합니다. (’static/dummyTweets.js’ 파일을 잘 읽어보세요.)
- 트윗 메시지가 있어야 합니다.
- li.tweet 엘리먼트의 후손 엘리먼트로 <div> 엘리먼트를 생성하고 dummyTweets의 트윗 내용을 <div> 의 텍스트 콘텐츠로 넣습니다.
- 클래스 이름은 tweet__message으로 지정합니다.
- 트윗이 dummyTweets의 길이만큼 있어야 합니다.
- dummyTweets에 트윗이 n개 전달되면, 화면에 트윗이 n개가 보여야 합니다
핵심 기능 구현하기
조건부 렌더링 기술 요구사항
- 조건부 렌더링을 활용해서 여러 트윗 중 유저 이름이 parkhacker인 배경색이 var(--point-color-tint-2)가 되도록 클래스(tweet__username--purple)를 지정해야 합니다. (tweet__username tweet__username--purple)
- ‘src/App.css’에 클래스가 미리 준비되어 있습니다. (className : 'tweet__username--purple')
const Tweets = () => {
return (
<ul className="tweets">
{dummyTweets.map((tweet) => {
return (
<li className="tweet" key={tweet.id}>
<div className="tweet__profile">
{/* TODO: 트윗 저자의 프로필 사진이 있어야 합니다. */}
<img src={tweet.picture} />
</div>
<div className="tweet__content">
<div className="tweet__userInfo">
{/* TODO : 유져 이름이 있어야 합니다. */}
{/* {<span className = "tweet__username">{`${tweet.username}`}</span>} */}
{/* TODO : 이름이 "parkhacker"인 경우, 이름 배경색을 rgb(235, 229, 249)으로 바꿔야 합니다. */}
{tweet.username === "parkhacker" ? <span className = "tweet__username tweet__username--purple">{tweet.username}</span> : <span className='tweet__username'>{tweet.username}</span>}
{/* TODO : 트윗 생성 일자가 있어야 합니다. */}
<span className = 'tweet__createdAt'>{tweet.createdAt}</span>
</div>
{/* TODO : 트윗 메세지가 있어야 합니다. */}
<div className='tweet__message'>{tweet.content}</div>
</div>
</li>
);
})}
</ul>
);
};
유저 이름이 parkhacker 면 바탕색을 보라색으로 아니면 그냥 이름만으로 표시 하기 위해서는 '삼항연산자'를 이용해야 합니다
삼항연산자?
(조건) ? true : false
조건이 참 일 경우 true , 조건이 거짓이면 false가 실행 됩니다.
그러면 의사코드를 짜본다면?
유저 이름이 parkhacker ? 참이면 유저네임 과 함께 배경색을 보라색으로! : 거짓이므로 유저네임만 나오고 배경색 추가 x
코드 로는?
{tweet.username === "parkhacker" ? <span className = "tweet__username tweet__username--purple">{tweet.username}</span> : <span className='tweet__username'>{tweet.username}</span>}
'코드스테이츠 FE 43기 도전기 > 실습' 카테고리의 다른 글
React Custom Component (0) | 2023.02.21 |
---|---|
React State & Props (0) | 2023.01.27 |
댓글