MyComponentClass.js
import { Component } from "react";
class MyComponentClass extends Component {
render() {
return (
<>
<h1>이름은 홍길동입니다.</h1>
<h2>나이는 23살입니다.</h2>
</>
)
}
}
export default MyComponentClass;
App.js
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
class App extends Component{
render() {
return (
<>
<MyComponentClass />
</>
);
}
}
export default App;
MyComponentFunction.js
function MyComponentFunction() {
return (
<>
<h1>이름은 홍길동입니다.</h1>
<h2>나이는 23살입니다.</h2>
</>
)
}
export default MyComponentFunction;
App.js
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
import MyComponentFunction from "./MyComponentFunction";
class App extends Component{
render() {
return (
<>
<h1>클래스형 컴포넌트</h1>
<MyComponentClass />
<hr />
<h1>함수형 컴포넌트</h1>
<MyComponentFunction />
</>
);
}
}
export default App;
컴포넌트는 일종의 객첸데, 그 객체에 내가 전달해주는 고유한 속성값이라고 생각하면 된다!
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
import MyComponentFunction from "./MyComponentFunction";
class App extends Component{
render() {
return (
<>
<h1>클래스형 컴포넌트</h1>
<MyComponentClass name="홍길동"/>
<hr />
<h1>함수형 컴포넌트</h1>
<MyComponentFunction name="고길동"/>
</>
);
}
}
export default App;
import { Component } from "react";
class MyComponentClass extends Component {
render() {
console.log(this);
console.log(this.props, typeof this.props);
return (
<>
<h1>이름은 {this.props.name}입니다.</h1>
<h2>나이는 23살입니다.</h2>
</>
)
}
}
export default MyComponentClass;
function MyComponentFunction(props) {
console.log(props);
return (
<>
<h1>이름은 {props.name}입니다.</h1>
<h2>나이는 23살입니다.</h2>
</>
)
}
export default MyComponentFunction;
App.js
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
import MyComponentFunction from "./MyComponentFunction";
class App extends Component{
render() {
return (
<>
<h1>클래스형 컴포넌트</h1>
<MyComponentClass name="홍길동" age={23} nickname={"길동"}/>
<hr />
<h1>함수형 컴포넌트</h1>
<MyComponentFunction name="고길동" age={40} nickname="길동"/>
</>
);
}
}
export default App;
import { Component } from "react";
class MyComponentClass extends Component {
render() {
console.log(this);
console.log(this.props, typeof this.props);
return (
<>
<h1>이름은 {this.props.name}입니다.</h1>
<h2>나이는 {this.props.age}살입니다.</h2>
<h2>별명은 {this.props.nickname}입니다.</h2>
</>
)
}
}
export default MyComponentClass;
this.props 너무 반복된다.
객체 비구조화를 이용해서 코드를 단순화
import { Component } from "react";
class MyComponentClass extends Component {
render() {
const { name, age, nickname } = this.props;
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>별명은 {nickname}입니다.</h2>
</>
)
}
}
export default MyComponentClass;
function MyComponentFunction(props) {
console.log(props);
return (
<>
<h1>이름은 {props.name}입니다.</h1>
<h2>나이는 {props.age}살입니다.</h2>
<h2>나이는 {props.nickname}살입니다.</h2>
</>
)
}
export default MyComponentFunction;
객체 비구조화를 이용해서 코드를 단순화
function MyComponentFunction(props) {
const {name, age, nickname} = props;
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>나이는 {nickname}살입니다.</h2>
</>
)
}
export default MyComponentFunction;
매개변수를 객체 비구조화하도록 정의
- 매개변수로 받을 때부터 비구조화해서 받아버리기 !
function MyComponentFunction({name, age, nickname}) {
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>나이는 {nickname}살입니다.</h2>
</>
)
}
export default MyComponentFunction;
wow 이렇게 쓰는 이유를 이제 정확히 이해했다 -!
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
import MyComponentFunction from "./MyComponentFunction";
class App extends Component{
render() {
return (
<>
<h1>클래스형 컴포넌트</h1>
<MyComponentClass />
<hr />
<h1>함수형 컴포넌트</h1>
<MyComponentFunction />
</>
);
}
}
export default App;
내용이 출력되지 않는다.
MyComponentClass.js
import { Component } from "react";
class MyComponentClass extends Component {
render() {
const {name, age, nickname} = this.props;
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>별명은 {nickname}입니다.</h2>
</>
)
}
}
MyComponentClass.defaultProps = {
name: "아무개",
age: 0,
nickname: "없음"
};
export default MyComponentClass;
함수형 컴포넌트의 경우 함수의 디폴트 파라미터로 대체
cf
{name = "아무개", age = 0, nickname = "없음"}
← 이런식으로 !
function MyComponentFunction({name = "아무개", age = 0, nickname = "없음"}) {
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>나이는 {nickname}살입니다.</h2>
</>
)
}
/*
MyComponentFunction.defaultProps = {
name: "아무개",
age: 0,
nickname: "없음"
};
*/
export default MyComponentFunction;
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
import MyComponentFunction from "./MyComponentFunction";
class App extends Component{
render() {
return (
<>
<h1>클래스형 컴포넌트</h1>
<MyComponentClass>
<i>어떤 내용</i>
</MyComponentClass>
<hr />
<h1>함수형 컴포넌트</h1>
<MyComponentFunction>
<i>어떤 내용</i>
</MyComponentFunction>
</>
);
}
}
export default App;
자식 컴포넌트의 내용(<i> 태그의 내용이 출력되지 않는 것을 확인)
import { Component } from "react";
class MyComponentClass extends Component {
render() {
const {name, age, nickname} = this.props;
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>별명은 {nickname}입니다.</h2>
<div>{this.props.children}</div>
</>
)
}
}
MyComponentClass.defaultProps = {
name: "아무개",
age: 0,
nickname: "없음"
};
export default MyComponentClass;
function MyComponentFunction({name = "아무개", age = 0, nickname = "없음", children}) {
return (
<>
<h1>이름은 {name}입니다.</h1>
<h2>나이는 {age}살입니다.</h2>
<h2>나이는 {nickname}살입니다.</h2>
<div>{children}</div>
</>
)
}
export default MyComponentFunction;
children은 이름을 정확히 지켜줘야 한다.
import { Component } from "react";
import MyComponentClass from "./MyComponentClass";
import MyComponentFunction from "./MyComponentFunction";
const datas = [
{name: "홍길동", age: 23, nickname: "호부호형을 원하는 자"},
{name: "고길동", age: 43, nickname: "둘리가 싫은 자"},
{name: "신길동", age: 50, nickname: "신길동 매운 짬뽕"}
];
class App extends Component{
render() {
return (
<>
<h1>클래스형 컴포넌트</h1>
{
datas.map(data =>
<MyComponentClass name={data.name} age={data.age} nickname={data.nickname}>
<i>어떤 내용</i>
</MyComponentClass>
)
}
<hr />
<h1>함수형 컴포넌트</h1>
{
datas.map(data =>
<MyComponentFunction>
<i>어떤 내용</i>
</MyComponentFunction>
)
}
</>
);
}
}
export default App;
<div style={{ width: 100, height: 100, borderRadius: 50, backgroundColor: 'red' }} />
내 실습 코드 ⬇️
App.js
import TrafficLight from "./TrafficLight";
function App() {
return (
<>
<TrafficLight/>
</>
)
}
export default App;
TrafficLight.js
import Lamp from "./Lamp";
const colors = [ {color: "red"}, {color: "yellow"}, {color: "green"}];
function TrafficLight() {
return (
<>
{
colors.map(data => <Lamp bgColor={data.color}/>)
}
</>
)
}
export default TrafficLight;
Lamp.js
function Lamp({ bgColor }) {
return (
<>
<div style={{ width: 100, height: 100, borderRadius: 50, backgroundColor: `${bgColor}` }} />
</>
)
}
export default Lamp;
App.js
import TrafficLight from "./TrafficLight";
function App() {
const tlSize = 100;
const tlColors = ["red", "blue", "green", "yellow"];
return (
<>
<TrafficLight size={tlSize} colors={tlColors} />
</>
);
}
export default App;
TrafficLight.js
function Lamp({ size, color }) {
return (
<div style={{ width: size, height: size, borderRadius: size / 2, backgroundColor: color }} />
);
}
export default function TrafficLight({ size, colors }) {
return (
<>
{
colors.map(color => <Lamp size={size} color={color} />)
}
</>
);
}
댓글을 작성한 작성자의 이미지, 작성자의 이름, 댓글 내용을 출력하는 컴포넌트를 제작
src 폴더 아래에 comment 폴더를 생성하고, Comment.js 파일을 추가
function Comment () {
return (
<>
<h1>댓글 컴포넌트</h1>
</>
)
}
export default Comment;
comment 폴더에 CommentList.js 파일을 추가
import Comment from "./Comment";
function CommentList() {
return (
<>
<Comment />
<Comment />
<Comment />
</>
)
}
export default CommentList;
App.js 파일에 CommentList 컴포넌트를 추가
import CommentList from "./comment/CommentList";
function App() {
return (
<>
<CommentList />
</>
)
}
export default App;
사람 이미지 ⇒ https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png
function Comment () {
return (
<div>
{/* 작성한 사람의 이미지 */}
<div>
<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png" alt="profile" />
</div>
{/* 작성한 사람의 이름과 댓글 내용 */}
<div>
<span>작성자 이름</span>
<span>댓글 내용</span>
</div>
</div>
)
}
export default Comment;
function Comment () {
const styles = {
wrapper: {
display: "flex",
flexDirection: "row",
border: "1px solid gray",
borderRadius: 16,
padding: 8,
margin: 8
},
image: {
width: 50,
height: 50,
borderRadius: 25
},
contentContainer: {
marginLeft: 10,
display: "flex",
flexDirection: "column",
},
nameText: {
color: "black",
fontSize: 16,
fontWeight: "bold",
marginBottom: 5
},
commentText: {
color: "black",
fontSize: 16
}
};
return (
<div style={styles.wrapper}>
{/* 작성한 사람의 이미지 */}
<div>
<img style={styles.image} src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png" alt="profile" />
</div>
{/* 작성한 사람의 이름과 댓글 내용 */}
<div style={styles.contentContainer}>
<span style={styles.nameText}>작성자 이름</span>
<span style={styles.commentText}>댓글 내용</span>
</div>
</div>
)
}
export default Comment;
function Comment (props) {
const styles = {
wrapper: {
display: "flex",
flexDirection: "row",
border: "1px solid gray",
borderRadius: 16,
padding: 8,
margin: 8
},
image: {
width: 50,
height: 50,
borderRadius: 25
},
contentContainer: {
marginLeft: 10,
display: "flex",
flexDirection: "column",
},
nameText: {
color: "black",
fontSize: 16,
fontWeight: "bold",
marginBottom: 5
},
commentText: {
color: "black",
fontSize: 16
}
};
return (
<div style={styles.wrapper}>
{/* 작성한 사람의 이미지 */}
<div>
<img style={styles.image} src="https://upload.wikimedia.org/wikipedia/commons/8/89/Portrait_Placeholder.png" alt="profile" />
</div>
{/* 작성한 사람의 이름과 댓글 내용 */}
<div style={styles.contentContainer}>
<span style={styles.nameText}>{props.name}</span>
<span style={styles.commentText}>{props.comment}</span>
</div>
</div>
)
}
export default Comment;
import Comment from "./Comment";
function CommentList() {
return (
<>
<Comment name="홍길동" comment="동쪽에 살아요." />
<Comment name="홍길남" comment="남쪽에 살아요." />
<Comment name="고길동" comment="둘리가 싫어요." />
</>
)
}
export default CommentList;
import Comment from "./Comment";
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요" },
{ name: "홍길남", comment: "남쪽에 살아요" },
{ name: "고길동", comment: "둘리가 싫어요" },
]
function CommentList() {
return (
<>
{ // 익명 함수 표현식
comments.map(function (data) {
return <Comment name={data.name} comment={data.comment} />;
})
}
{ // 화살표 함수
comments.map(data => {
return <Comment name={data.name} comment={data.comment} />;
})
}
{ // 화살표 함수 축약
comments.map(data => <Comment name={data.name} comment={data.comment} />)
}
</>
)
}
export default CommentList;
import Comment from "./Comment";
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요" },
{ name: "홍길남", comment: "남쪽에 살아요" },
{ name: "고길동", comment: "둘리가 싫어요" },
]
function CommentList() {
return (
<>
{ // 익명 함수 표현식
comments.map(function (data, index) {
return <Comment key={index} name={data.name} comment={data.comment} />;
})
}
{ // 화살표 함수
comments.map((data, index) => {
return <Comment key={index} name={data.name} comment={data.comment} />;
})
}
{ // 화살표 함수 축약
comments.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} />)
}
</>
)
}
export default CommentList;
이렇게 map 함수의 두 번째 인자인 index 를 key 값으로 넣어주면 된다.
import Comment from "./Comment";
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg"},
{ name: "홍길남", comment: "남쪽에 살아요", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
{ name: "고길동", comment: "둘리가 싫어요", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" },
]
function CommentList() {
return (
<>
{ // 익명 함수 표현식
comments.map(function (data, index) {
return <Comment key={index} comment={data} />;
})
}
{ // 화살표 함수
comments.map((data, index) => {
return <Comment key={index} comment={data} />;
})
}
{ // 화살표 함수 축약
comments.map((data, index) => <Comment key={index} comment={data}/>)
}
</>
)
}
export default CommentList;
function Comment ({comment: c}) {
const {name, comment, picture} = c;
const styles = {
wrapper: {
display: "flex",
flexDirection: "row",
border: "1px solid gray",
borderRadius: 16,
padding: 8,
margin: 8
},
image: {
width: 50,
height: 50,
borderRadius: 25
},
contentContainer: {
marginLeft: 10,
display: "flex",
flexDirection: "column",
},
nameText: {
color: "black",
fontSize: 16,
fontWeight: "bold",
marginBottom: 5
},
commentText: {
color: "black",
fontSize: 16
}
};
return (
<div style={styles.wrapper}>
{/* 작성한 사람의 이미지 */}
<div>
<img style={styles.image} src={picture} alt="profile" />
</div>
{/* 작성한 사람의 이름과 댓글 내용 */}
<div style={styles.contentContainer}>
<span style={styles.nameText}>{name}</span>
<span style={styles.commentText}>{comment}</span>
</div>
</div>
)
}
export default Comment;
또는 props를 이렇게 받을 수도 있다
function Comment (props) {
const {comment: c} = props;
const {name, comment, picture} = c;
...
import Comment from "./Comment";
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg"},
{ name: "홍길남", comment: "남쪽에 살아요", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
{ name: "고길동", comment: "둘리가 싫어요", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" },
]
function CommentList() {
return (
<>
<h1>모두 출력</h1>
{
comments.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={data.picture}/>)
}
<h1>홍길동만 출력</h1>
{ // filter 메서드를 이용하는 경우
comments
.filter(data => data.name === "홍길동")
.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={data.picture}/>)
}
{ // && 연산자를 이용한 조건부 렌더링
comments
.map((data, index) => data.name === "홍길동" && <Comment key={index} name={data.name} comment={data.comment} picture={data.picture}/>)
}
{ // 삼항연산자를 이용한 조건부 렌더링
comments
.map((data, index) => data.name === "홍길동" ? <Comment key={index} name={data.name} comment={data.comment} picture={data.picture}/> : null)
}
</>
)
}
export default CommentList;
import Comment from "./Comment";
const users = [
{ name: "홍길동", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg"},
{ name: "홍길남", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
{ name: "고길동", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" },
];
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요" },
{ name: "홍길남", comment: "남쪽에 살아요" },
{ name: "고길동", comment: "둘리가 싫어요" },
];
function getUserPicture(name) {
return users.filter(user => user.name === name)[0].picture;
}
function CommentList() {
return (
<>
<h1>모두 출력</h1>
{
comments.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={getUserPicture(data.name)} />)
}
</>
)
}
export default CommentList;
이렇게도 가능 ! ⬇️
{
comments.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={users.filter(user => user.name === data.name)[0].picture} />)
}
filter 라서 배열로 반환해주기 때문에 결과값이 하나라도 [0] 이런식으로 첫 번째 요소를 가져와줘야 한다.
{
comments.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={users.find(user => user.name === data.name).picture} />)
}
import Comment from "./Comment";
const users = [
{ name: "홍길동", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg"},
{ name: "홍길남", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
{ name: "고길동", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" },
];
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요" },
{ name: "홍길남", comment: "남쪽에 살아요" },
{ name: "고길동", comment: "둘리가 싫어요" },
];
const commentsWithPicture = comments.map(c => ({...c, picture: users.filter(u => u.name === c.name)[0].picture}));
function CommentList() {
return (
<>
<h1>모두 출력</h1>
{
commentsWithPicture.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={data.picture} />)
}
</>
)
}
export default CommentList;
find 사용해서 이렇게도 가능 !
const commentsWithPicture = comments.map(c => ({...c, picture: users.find(u => u.name === c.name).picture}));
import Comment from "./Comment";
const users = [
{ name: "홍길동", regno: "701010-1457934", picture: "https://png.pngtree.com/png-clipart/20190705/original/pngtree-vector-business-men-icon-png-image_4186858.jpg"},
{ name: "홍길남", regno: "201010-3457934", picture: "https://png.pngtree.com/png-clipart/20190630/original/pngtree-vector-avatar-icon-png-image_4162757.jpg" },
{ name: "고길동", regno: "211010-4157934", picture: "https://png.pngtree.com/png-clipart/20190520/original/pngtree-male-worker-icon-graphic-png-image_3668949.jpg" },
];
const comments = [
{ name: "홍길동", comment: "동쪽에 살아요" },
{ name: "홍길남", comment: "남쪽에 살아요" },
{ name: "고길동", comment: "둘리가 싫어요" },
];
function getUserGender (name) {
const regno = users.find(u => u.name === name).regno;
return [1, 3].includes(Number(regno[7])) ? "남" : "여";
}
const commentsWithPicture = comments.map(c =>
({
...c,
picture: users.find(u => u.name === c.name).picture,
name: `${c.name} (${getUserGender(c.name)})`
}));
function CommentList() {
return (
<>
<h1>모두 출력</h1>
{
commentsWithPicture.map((data, index) => <Comment key={index} name={data.name} comment={data.comment} picture={data.picture} />)
}
</>
)
}
export default CommentList;
컴포넌트 내부에서 읽고 업데이트할 수 있는 값
state 변수 값이 변경되면 리렌더링이 발생 <= 클래스형 컴포넌트는 setState() 메서드를, 함수형 컴포넌트는 useState 훅 함수가 반환하는 세터 함수를 이용해서 값을 변경
화면에 즉시 반영되는 값만 쓰자!
import { Component } from "react";
import Counter from "./Counter";
class App extends Component {
render() {
return (
<>
<Counter />
</>
);
}
}
export default App;
import { Component } from "react"
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
number: 0
};
}
render() {
return (
<>
<h1>{this.state.number}</h1>
<button onClick={() => {
console.log(this.state.number);
this.state.number = this.state.number + 1;
}}>
하나 증가
</button>
</>
);
}
}
export default Counter;
하나 증가를 누르면 숫자가 올라가야하는데 반영이 안 된다.
리렌더링이 안 된다,,,
버튼을 클릭해도 변경 숫자가 화면에 표시되지 않는다 😭
<h1>{this.state.number}</h1>
<button onClick={() => {
console.log(this.state.number);
// this.state.number = this.state.number + 1;
this.setState({ number: this.state.number + 1 });
}}>
하나 증가
</button>
비구조화 할당!
import { Component } from "react"
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
number: 0,
fixedNumber: 10
};
}
render() {
const { number, fixedNumber } = this.state;
return (
<>
<h1>{number}</h1>
<button onClick={() => {this.setState({ number: number + 1 })}}>
하나 증가
</button>
<h1>{fixedNumber}</h1>
</>
);
}
}
export default Counter;
import { Component } from "react"
class Counter extends Component {
state = {
number: 0,
fixedNumber: 10
};
render() {
const { number, fixedNumber } = this.state;
return (
<>
<h1>{number}</h1>
<button onClick={() => {this.setState({ number: number + 1 })}}>
하나 증가
</button>
<h1>{fixedNumber}</h1>
</>
);
}
}
export default Counter;
주로 이렇게 많이 쓴다.
updator 함수 형태로 넣어줘야한다.
import { Component } from "react"
class Counter extends Component {
state = {
number: 0,
fixedNumber: 10
};
render() {
const { number, fixedNumber } = this.state;
return (
<>
<h1>{number}</h1>
<button onClick={() => {
this.setState(prevState => ({ number: prevState.number + 1}));
this.setState(prevState => ({ number: prevState.number + 1}));
this.setState(prevState => ({ number: prevState.number + 1}));
this.setState(prevState => ({ number: prevState.number + 1}));
this.setState(prevState => ({ number: prevState.number + 1}));
}}>
다섯 증가
</button>
<h1>{fixedNumber}</h1>
</>
);
}
}
export default Counter;
업데이트 되고나서 호출되는 함수 !!!
<button onClick={() => {
this.setState({ number: number + 1 }, () => {
console.log('setState가 호출되었습니다.', this.state, number);
});
}}>
다섯 증가
</button>
Say.js
import { useState } from "react";
function Say () {
const [message, setMessage] = useState('');
const [color, setColor] = useState('black');
return (
<>
<h1 style={{ color }}>{message}</h1> {/* 단축 속성명 color: color -> color */}
<button onClick={() => setMessage("입장합니다.")}>입장</button>
<button onClick={() => setMessage("퇴장합니다.")}>퇴장</button>
<button onClick={() => setColor("red")}>빨간색</button>
<button onClick={() => setColor("blue")}>파란색</button>
<button onClick={() => setColor("yellow")}>노란색</button>
</>
)
}
export default Say;
상태변수만 바꾸면 돼서 편하게 사용이 가능하다 !!!
onClick 콜백함수 사용 이유
state 값을 변경할 때 setState (클래스형 컴포넌트) 또는 useState 훅 함수가 반환한 setter 함수 (함수형 컴포넌트) 를 이용해야 한다.
→ 그렇지 않으면 변경된 값이 화면에 반영될 수 없다. (forceUpdate() 함수를 이용해서 강제로 반영할 수 있으나, 절대 권장하지 않는다. - 리액트의 생명주기를 깨기 때문)
배열 또는 객체를 업데이트해야 하는 경우, 주소를 공유하기 때문에 그 사본을 만들고 그 사본의 값을 업데이트 후 setState 또는 setter 함수를 통해서 반영해야 한다.
const obj = { a: 1, b: 2, c: 3 };
const newObj = { ...obj, b: 20 };
const arr = [1, 2, 3, 4];
const newArr1 = [...arr]; // [1, 2, 3, 4]
const newArr2 = arr.concat(100); // [1, 2, 3, 4, 100]
const newArr3 = arr.filter(i => i % 2 === 0); // [2, 4]
const newArr4 = arr.map(i => i * i); // [1, 4, 9, 16]
🚨 주의
const newArr5 = arr.push(100); // 기존 arr 배열에 100을 추가하고, 배열 길이를 반환
onClick, onKeyUp
<button onclick="javascript: alear('clicked')" /> // (X)
<button onClick={ () => {...} } /> // 이벤트 핸들러 함수를 직접 정의
// 외부에 정의한 함수 이름을 전달. 일반적으로 이벤트 핸들러 함수 이름은 on 또는 handler 접두어를 사용
<button onClick={ onClick } />
<button onClick={ handlerClick } />
DOM 요소 : HTML 태그들
ex) <div>
<div onMouseOver={ () => {...} } /> ... </div> // DOM 요소(=태그)에 이벤트 설정이 가능
<MyComponent onMouseOver={ () => {...} } /> ... </MyComponent> // 컴포넌트에 이벤트를 설정할 수 없다. 여기서 onMouseOver는 props로 동작해서 props 변수로 함수가 전달된다.
증가 버튼을 클릭하면 OOOO 영역에 "현재 카운드는 OOO입니다."를 출력하도록, App, Todo, Title 컴포넌트를 작성해 보세요.
<App> <Todo> <Title title="OOOO"> <p>OOOO</p> </Title> <button>증가</button> </Todo> </App>
내 실습 코드
App.js
import { Todo } from "./Todo";
function App() {
return (
<>
<Todo />
</>
);
}
export default App;
Todo.js
import { useState } from "react"
import { Title } from "./Title"
export const Todo = () => {
const [count, setCount] = useState(0);
return (
<>
<Title title={count} />
<button onClick={() => setCount(count + 1)}>증가</button>
</>
)
}
Title.js
export const Title = ({title}) => {
return (
<p>현재 카운트는 {title}입니다.</p>
)
}
강사님 코드
import { useState } from "react";
function Title({title}) {
return (
<p>현재 카운트는 {title}입니다.</p>
);
}
function Todo() {
const [count, setCount] = useState();
return (
<>
<Title title={count}></Title>
<button onClick={() => setCount(count + 1)}>증가</button>
</>
);
}
function App() {
return (
<>
<Todo />
</>
);
}
export default App;