props와 state는 렌더링 결과물에 영향을 주는 정보를 가지는 일반 javascript 객체다.
컴포넌트의 속성(property)으로 외부로부터 전달받는 변하지 않는 값을 의미하며, 웹 앱에서 해당 컴포넌트가 가진 속성에 해당한다.
props는 어떤 타입의 값도 넣어 전달할 수 있도록 객체 형태를 가진다.
props는 변경되지 않는 읽기 전용 객체다.
function Parent() {
return (
<div>
<h1>parent</h1>
<Child me='child'/>
//<Child>child</Child>
</div>
);
};
function Child(props) {
return (
<div>{props.me}</div>
//<div>{props.chilren}</div> => props.children은 해당 컴포넌트의 태그 사이 value에 접근할 수 있다.
);
};
컴포넌트 내부에서 변할 수 있는 값으로 컴포넌트 내에서 관리된다.
useState는 상태 유지 값과 그 값을 갱신하는 함수를 배열 형태로 반환한다.
import {useState} from 'react';
const [state, setState] = useState();
useState에 인자는 state의 초기값으로 전해진다. 첫 렌더링 시 한번만 적용된다.
state의 변경은 렌더링을 불러오지만 갱신함수 없이 직접적으로 변경을 시도하면 렌더링이 작동하지 않거나 state변경이 이루어지지 않는다.
상태값 갱신
갱신 함수에 들어온 값으로 state가 '변경'된다.
import {useState} from 'react';
function App() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count++);
}
return (
<div>{count}</div>
<button onClick={handleClick}>count up</button> {/*누를때마다 count가 증가*/}
)
}
이벤트의 이름은 카멜케이스로 작성한다.
함수를 직접 작성하거나 정의된 함수를 할당한다.
<button onClick={handleCount}>count up</button>
<button onClick={()=>setCount(count++)}>count up</button>
onClick
element를 클릭 했을때 발생하는 이벤트 ex) <button>
등
onChange
from element의 사용자 입력값이 갱신 되었을 때 발생하는 이벤트 ex) <input>, <textarea>, <select>
등
import {useState} from 'react';
function App() {
const [text, setText] = useState('');
const [pick, setPick] = useState(')
function handleChange(e) {
setChange(e.target.value);
}
const handleSelect = e => {
setPick(e.target.value);
}
const word = [a, b, c, d];
const options = word.map(x=><optoin>{x}</option>);
return (
<input type='text' onChange={handleChange}></input>
<select onChange={handleSelect}>{options}</select>
)
}
test의 마지막 단계인 새로운 tweet 추가는 state와 eventhandler를 통해서 구현한다. tweets 컴포넌트에 새롭게 추가할 tweet과 작성자의 정보 들을 담을 객체를 생성하고, dummyData를 초기값으로 가지는 state를 선언해 구현한다.
import React, {useState} from 'react';
const Tweet = ({tweet}) => {
{/*Tweet의 인자는 props로 받아서 const tweet=props.tweet으로 사용할 수도 있다.*/}
{/*날짜를 한국식으로 변경*/}
const parsedDate = new Date(tweet.createdAt).toLocaleDateString('ko-kr');
{/*props로 데이터를 받아와 필요한 요소들을 용도에 맞게 사용*/}
return (
<li className="tweet" id={tweet.id}>
<div className="tweet__profile">
<img src={tweet.picture} /> {/*사용자 사진*/}
</div>
<div className="tweet__userInfo--wrapper">
<span className="tweet__username">{tweet.username}</span> // {/*사용자 이름*/}
<span className="tweet__createdAt">{parsedDate}</span> // {/*생성날짜*/}
</div>
<div className="tweet__message">{tweet.content}</div> {/*사용자가 작성한 메세지*/}
</div>
</li>
);
};
const Tweets = () => {
// tweet데이터들을 담을 state를 만든다.
const [tweets, setTweets] = useState(dummyTweets);
// 사용자가 tweet메세지를 작성하고 제출 버튼을 누르면 tweet을 추가하는 이벤트 핸들러
const handleButtonClick = (event) => {
const tweet = {
id: tweets.length+1,
username: username, //사용자의 이름
picture: 'https://randomuser.me/api/portraits/men/98.jpg', // 사용자의 이미지
title: 'new Tweet',
content: msg, // 사용자가 작성한 tweet 메세지
createdAt: new Date().toLocaleDateString('ko-KR'), // 작성한 날짜
updatedAt: new Date().toLocaleDateString('ko-KR'), // 업로드한 날짜
};
const newTweets = [tweet, ...tweets]; // 새로운 tweet을 기존의 tweets 목록의 앞에다가 추가
setTweets(newTweets);
};
return (
<React.Fragment>
{/*..중략*/}
<div className="tweetForm__submitIcon"> </div>
{/*tweet를 제출할 버튼 onclick에 위에서 정의한 함수를 할당*/}
<button className="tweetForm__submitButton" onClick={handleButtonClick}>Tweet</button>
</div>
{/*..중략*/}
<ul className="tweets">
{/*map()으로 존재하는 데이터 개수만큼 Tweet 컴포넌트를 생성 */}
{filters.map(tweet=><Tweet key={tweet.id} tweet={tweet} />>)}</ul>
<Footer />
</React.Fragment>
);
};
export default Tweets;