h e 1 1 o !
React props & state 과제 리뷰 본문
과제 진행하며
실시간 세션 듣고 나니까 감이 온다. 너무 어려워서 흥미를 잃은 상태였는데 알아듣기 시작하니 재미있다.
어려웠던 만큼 한줄한줄 해석하고 넘어가야겠다. 내가 어려웠던 부분과 주요 개념들을 먼저 살펴 보고 과제 중 tweets.js 만 볼 것.
리액트는 기능과 구현이 함께 되어 있어서 그런지 잘안읽히고 뭘 하는 컴포넌트인지 스스로 구분이 안되어서 과제 진행이 어려웠다.
계속 연습하며 익혀야 한다. 공식문서 참고하며 공부하기!
https://ko.reactjs.org/docs/faq-state.html#what-does-setstate-do
컴포넌트 State – React
A JavaScript library for building user interfaces
ko.reactjs.org
보충이 필요한 부분
- 아래에 정리할 리액트 주요개념
- 리액트 컴포넌트 위치, 역할 파악
과제에서 얻은 주요개념
- state 사용방법 (setState와 렌더링의 관계)
- props 사용방법
- 태그에 이벤트 넣기, 이벤트핸들링
1. setState와 렌더링의 관계
setState()는 컴포넌트의 state 객체에 대한 업데이트를 실행합니다. state가 변경되면, 컴포넌트는 리렌더링됩니다.
setState는 state 업데이트 -> 리렌더링 하여 최신 정보를 보여줌
2. props 사용방법
state가 컴포넌트 안에서만 관리되는 반면, props는 인수처럼 (자식)컴포넌트에 전달된다.
부모 컴포넌트에 들어온 자식 컴포넌트 태그에 props(속성)를 만들어 주고,
자식 컴포넌트에서 (props)로 받아와서 해당 속성을 사용하면 된다.
props의 이름은 꼭 props가 아니어도 된다.
3. 태그에 이벤트 넣기, 이벤트핸들링
React의 이벤트 처리(이벤트 핸들링; Event handling) 방식은 DOM의 이벤트 처리 방식과 유사. 단, 몇 가지 문법 차이가 있다.
- React 에서 이벤트는 소문자 대신 카멜 케이스(camelCase) 를 사용합니다.
- JSX를 사용하여 문자열이 아닌 함수로 이벤트 처리 함수(이벤트 핸들러; Event handler)를 전달합니다.
<button onclick="handleEvent()">Event</button> // JS에서 이벤트 핸들링
<button onClick={handleEvent}>Event</button> // React에서 이벤트 핸들링
이벤트를 읽어올 태그에 on__ 메서드 속성과 함수이름을 넣어주고,
함수를 바깥에서 만든다.
발생한 이벤트에 대한 정보는 event.target.value로 이벤트 함수에 전달할 수 있다.
함수를 바깥에 따로 위치시키는 방법 말고, 화살표 함수로 태그 안에 직접 넣는 방법도 있다.
아래는 onChange 이벤트핸들링 예시이다.
function NameForm() {
const [name, setName] = useState("");
const handleChange = (e) => {
setName(e.target.value);
}
return (
<div>
<input type="text" value={name} onChange={handleChange}></input>
<h1>{name}</h1>
</div>
)
};
과제에서 중요한 부분
▼ (새로 추가된 트윗 + 원래 트윗들)로 트윗 리스트를 갱신하는 작업 (setState)
새로 변수를 선언해서 그 변수에 (새롭게 추가된 트윗 + 원래 트윗)를 넣어준다.
그 변수를 setTweets 함수에 넣어주면 tweets의 내용이 (새롭게 추가된 트윗 + 원래 트윗)로 렌딩 된다.
이 글의 초반부, 주요개념 1번에 자세히 나온 setState와 랜딩의 관계에 대한 개념 참고.
const newTweet = [tweet, ...tweets]; // tweet을 앞에, tweets 객체들을 스프레드 문법으로 뒤로 오게 했다
setTweets(newTweet);
};
▼ tweets 객체들을 뿌려서 Tweet 컴포넌트에 넣어주는 부분 (배열의 객체들을 컴포넌트로 넣어 연속적인 컴포넌트들 만들기)
{tweets.map((tweet) => {
return <Tweet tweet={tweet} key={tweet.id} />;
})}
배열에 매핑하는 방식으로, 배열 안의 객체들을 Tweet 컴포넌트로 리턴한다. Tweet 컴포넌트가 연속적으로 오게 된다.
Tweet 컴포넌트의 속성(props)으로, 'tweet'을 넣어준다.
'tweet'을 props로 써서 자식 컴포넌트인 Tweet에서 'tweet'의 값을 활용할 수 있다.
키는 tweet, 밸류는 매핑해서 들어오는 하나의 트윗 객체이고, 키 속성은 매핑으로 들어오는 하나의 트윗의 아이디이다.
tweets.js 코드
// TODO : useState를 react로 부터 import 합니다.
import React, { useState } from "react"; //useState 함수를 사용하기 위해 임포트 한다
import Footer from "../Footer";
import Tweet from "../Components/Tweet";
import "./Tweets.css";
import dummyTweets from "../static/dummyData";
const Tweets = () => {// Tweets 컴포넌트는 트윗을 입력, 갱신해서 보여주는 컴포넌트이다
const [username, setUsername] = useState("parkhacker"); //username을 갱신하기 위해 사용하는 useState
const [msg, setMsg] = useState("");//msg를 갱신하기 위해 사용하는 useState
const [tweets, setTweets] = useState(dummyTweets);//tweets를 갱신하기 위해 사용하는 useState
//tweets는 트윗 객체들
const getRandomNumber = (min, max) => {
return parseInt(Math.random() * (Number(max) - Number(min) + 2));
}; //img 랜덤 하게 만들어주는 변수
const handleButtonClick = (event) => { //버튼을 클릭하면 발생하는 함수 handleButtonClick 표현
//버튼을 클릭하면 event.target.value에 정보를 담아와 새로운 tweet 객체를 만든다. 새로운 객체를 만들기 위한 틀
const tweet = {
id: tweets.length + 1,
username: username,
picture: `https://randomuser.me/api/portraits/women/${getRandomNumber(
1,
98
)}.jpg`,
content: msg,
createdAt: new Date(),
updatedAt: new Date(),
};
// ▼ < // 새롭게 추가된 트윗 + 원래 트윗들로 트윗 리스트를 갱신하는 작업 // >
const newTweet = [tweet, ...tweets]; // tweet을 앞에, tweets 객체들을 스프레드 문법으로 뒤로 오게 했다
setTweets(newTweet);
};
const handleChangeUser = (event) => {
// TODO : Tweet input 엘리먼트에 입력 시 작동하는 함수를 완성하세요.
setUsername(event.target.value); //username을 event.target.value로 갱신
};
const handleChangeMsg = (event) => {
// TODO : Tweet textarea 엘리먼트에 입력 시 작동하는 함수를 완성하세요.
setMsg(event.target.value); //msg를 event.target.value로 갱신
};
return (
<React.Fragment>
<div className="tweetForm__container">
<div className="tweetForm__wrapper">
<div className="tweetForm__profile">
<img src="https://randomuser.me/api/portraits/men/98.jpg" />
</div>
<div className="tweetForm__inputContainer">
<div className="tweetForm__inputWrapper">
<div className="tweetForm__input">
<input
type="text"
defaultValue="parkhacker"
placeholder="your username here.."
className="tweetForm__input--username"
onChange={handleChangeUser} //username이 들어오는 input 태그에 onChange 이벤트와 함수를 추가했다
></input>
<textarea
className="tweetForm__input--message"
onChange={handleChangeMsg} //username이 들어오는 textarea 태그에 onChange 이벤트와 함수를 추가했다
></textarea>
</div>
<div className="tweetForm__count" role="status">
<span className="tweetForm__count__text">
{/* TODO : 트윗 총 개수를 보여줄 수 있는 Counter를 작성하세요. */}
{"total:" + tweets.length} //{ } 중괄호 안은 JS 문법을 사용할 수 있다. js에서 문자열과 객체 사용하는 방법과 같음
</span>
</div>
</div>
<div className="tweetForm__submit">
<div className="tweetForm__submitIcon"></div>
{/* TODO : 작성한 트윗을 전송할 수 있는 button 엘리먼트를 작성하세요. */}
<button
className="tweetForm__submitButton"
onClick={handleButtonClick} //username이 들어오는 button 태그에 onClick 이벤트와 함수를 추가했다
>
Tweet
</button>
</div>
</div>
</div>
</div>
<div className="tweet__selectUser"></div>
<ul className="tweets">
// ▼ < // tweets 객체들을 뿌려서 Tweet 컴포넌트에 넣어주는 부분 // > //
{tweets.map((tweet) => { //맵을 이용해 tweets 배열의 객체, tweet들을 Tweet 컴포넌트에 넣어줌
return <Tweet tweet={tweet} key={tweet.id} />; // 컴포넌트의 props로 tweet들을, 키로 tweet들의 id를 넣어줌
})}
</ul>
<Footer />
</React.Fragment>
);
};
export default Tweets;
'c o d e r e v i e w' 카테고리의 다른 글
React / Expense 양방향 바인딩 (0) | 2022.06.13 |
---|