React 수업이 시작되었다. 과제는 Twitter와 유사한 Twittler를 React로 개발하는 것이며 오늘은 인트로로 JSX 기본문법을 익히는 학습을 하였다.
(사실 과제 시작부터 npm run test 오류가 발생하여 제대로 내용을 학습하지 못했다🥲npm run start는 작동하여 어찌어찌 구현된 화면만 보고 과제를 진행했다. 다만 제출은 하지 못한... )
📌 React 특징
- 선언형(→ 명시적이다)
코드를 자세히 분석하지 않고도 코드의 의도를 분명하게 알 수 있다.
html / js ⇒ jsx(html & js) 하나의 파일에 명시적으로 작성한다.- 컴포넌트 기반
구조와 동작에 대한 코드를 한 묶음으로 한다. 컴포넌트 단위로 분리하면 어떠한 기능이 동작하지 않을 때, 해당 기능을 구현하는 컴포넌트를 우선점검이 가능하다. 따라서 유지보수성이 높다.- 범용성
react는 JavaScript의 라이브러리다. 따라서 기존의 js 어플리케이션에 react를 추가하여 개발하는 것이 가능하다. → 프로젝트를 뒤엎지 않고 일부만 수정이 가능하다.
📌 JSX란?
JavsScript를 확장한 문법. JSX가 없어도 react 요소는 만들 수 있지만 복잡하고 가독성이 떨어진다.
💡 JSX를 브라우저가 이해 가능하도록 컴파일 하기 위해서는 Bable이 필요하다.
📌 JSX 규칙
하나의 엘리먼트 안에 모든 엘리먼트가 포함되어야 한다. 즉, 최상위에서 opening tag와 closing tag로 감싸주어야 한다.
클래스는
className으로 표기해야한다. class로 작성하면 html 속성이 아닌 javascript 클래스로 이해한다.SX에서 JavaScript를 쓰고자 한다면, 꼭 {중괄호} 를 이용해야 한다. 중괄호를 사용하지 않으면 일반 텍스트로 인식한다.
사용자 정의 컴포넌트는 대문자 로 시작해야 한다. 소문자로 시작하면 일반적인 html 엘리먼트로 인식한다.
조건부 렌더링은 if문이 아닌 삼항연산자를 이용해야 한다. if문은 표현식이 아니기 때문이다.
React 에서 여러 개의 html 엘리먼트를 표시할 때는 "map()" 함수를 사용한다.
map 함수를 사용할 때는 반드시 최상위 엘리먼트에 "key" JSX 속성을 넣어야 한다.
→ key 속성값은 가능하면 데이터에서 제공하는 id를 할당해야 한다. key 속성값은 id와 마찬가지로 변하지 않고, 예상 가능하며, 유일해야 하기 때문이다.
→ 정 고유한 id가 없는 경우에만 배열 인덱스를 넣어서 해결할 수 있지만, 배열 인덱스는 최후의 수단(as a last resort)으로만 사용한다. 만약 배열이 변한다면 리액트는 이해하지 못하고 리렌더링되어 웹 성능에 악영향을 미치기 때문이다.
→ 임시키로 uuid, nanoid 라이브러리 사용하는 방법도 있음function Blog() { const blogs = posts.map((post) => ( <div key={post.id}> // key <h3>{post.title}</h3> // js 자료는 {중괄호} 사용 <p>{post.content}</p> </div>)); return <div className="post-wrapper">{blogs}</div>; }
const App = () => {
return (
<div className="App">
<main>
<Sidebar /> // APP component의 지막 요소 다음에 sidebar 컴포넌트를 적어주면 된다.
<Features />
</main>
</div>
);
};
const Sidebar = () => {
return (
<section className="sidebar">
<i className='far fa-comment-dots'></i> // i태그를 사용하여 아이콘을 넣어주었다. p, span태그 다되긴 한다.
</section>
);
};
const Features = () => {
return (
<section className="features">
<div className="tweetForm__container">
<div className="tweetForm__wrapper">
<div className="tweetForm__profile"></div>
<Counter /> // 마지막 요소 밑에 후손 컴포넌트로 넣어줌!
<Footer />
</div>
</div>
<Tweets />
</section>
);
};
const Counter = () => {
return (
<div className="tweetForm__input">
<div className="tweetForm__inputWrapper">
<div className="tweetForm__count" role="status">
{`total : ${dummyTweets.length}`} // JSX 문법임! JSX에서 JavaScirpt를 쓰고자 한다면, {중괄호}를 이용해야한다.(쓰지 않으면 텍스트로 인식함)
</div>
</div>
</div>
);
};
const Footer = () => {
return (
<footer> // 시멘티 태그인 footer를 사용함
<img id="logo" src={`${process.env.PUBLIC_URL}/codestates-logo.png`} />
Copyright @ 2022 Code States
</footer>
);
};
const Tweets = () => {
return (
<ul className="tweets">
{dummyTweets.map((tweet) => {
// (5) parkClassName 변수에 조건을 줌
// 더미 데이터의 유저 이름이 parkhacker 컬러 클래스 추가
// 아니라면 그냥 유저 이름 클래스만 준다.
const parkClassName =
tweet.username === 'parkhacker'
? 'tweet__username tweet__username--purple'
: 'tweet__username';
return (
<li className="tweet" key={tweet.id}>
<div className="tweet__profile">
// (1) 이미지
<img src={tweet.picture}></img> // img src 속성에 더미데이터의 picture 데이터를 연결했다.
</div>
<div className="tweet__content">
<div className="tweet__userInfo">
// (2)(5) 유저이름
<span className={parkClassName}>{tweet.username}</span>
// (3) 생성날짜
<span className='tweet__createdAt'>{tweet.createdAt}</span>
</div>
// (4) 메세지
<div className='tweet__message'>{tweet.content}</div>
</div>
</li>
);
})}
</ul>
);
};