[React]Component
이 글은 [리액트를 다루는 기술](저자 김민준, 출판사 길벗) 교재를 보고 공부하며 정리한 글임.
전에 보았던 App 컴포넌트는 함수형 컴포넌트
컴포넌트를 선언하는 방식은 두가지
함수형 컴포넌트와
클래스 컴포넌트
차이점은 클래스형 컴포넌트의 경우 이후 배울 state 기능 및 라이프사이클 기능을 사용할 수 있다는 것과
임의 메서드를 정의할 수 있다는 것
클래스형 컴포넌트에서는 render 함수가 꼭 있어야 하고 그 안에서 보여줄 JSX 를 반환해야함
하지만 함수형 컴포넌트의 단점은 Hooks라는 기능이 도입되면서 해결되었음
이젠 함수형 컴포넌트와 Hooks를 사용하도록 권장함
첫 컴포넌트 생성
src에 MyComponent라는 js 파일 만들어 주고
import React from 'react';
const MyComponent = ()=>{
return <div>나의 새롭고 멋진 컴포넌트</div>;
};
export default MyComponent
function 키워드 사용 대신에 () => {} 를 사용하여 함수를 만들어 주었다.
ES6의 화살표 함수 문법
일반함수는 자신이 종속된 객체를 this로 가리키고
화살표 함수는 자신이 종속된 인스턴스를 가리킨다(90페이지)
export default MyComponent;
라는 이 코드는 다른 파일에서 이 파일을 import 할때 위에서 선언한 MyComponent 클래스를 불러오도록 설정
MyComponent.js
import React from 'react';
const MyComponent = ()=>{
return <div>나의 새롭고 멋진 컴포넌트</div>;
};
export default MyComponent;
App.js
import React from 'react';
import MyComponent from './MyComponent';
const App =() => {
return <MyComponent />;
};
export default App;
브라우저에서 렌더링 되었는지 확인
props 값을 지정해보기
App.js
import React from 'react';
import MyComponent from './MyComponent';
const App =() => {
return <MyComponent name="React" />;
};
export default App;
props의 기본값 defaultProps
name 값을 지우고 저장하면 브라우저에는 이름이 비어보일 것이다.
따로 props의 값을 지정하지 않았을때 보여주는 기본값
App.js
import React from 'react';
import MyComponent from './MyComponent';
const App =() => {
return <MyComponent />;
};
export default App;
MyComponent.js
import React from 'react';
const MyComponent = props => {
return <div>안녕하세요, 제 이름은 {props.name}입니다.</div>;
};
MyComponent.defaultProps ={
name : '비어있는 이름'
};
export default MyComponent;
결과 화면
컴포넌트 태그 사이의 내용을 보여주는 children
App.js
import React from 'react';
import MyComponent from './MyComponent';
const App =() => {
return <MyComponent>리액트</MyComponent>;
};
export default App;
MyComponent.js
import React from 'react';
const MyComponent = props => {
return(
<div>
안녕하세요, 제 이름은 {props.name}입니다.<br />
children 값은 {props.children}
입니다.
</div>
);
};
MyComponent.defaultProps ={
name : '비어있는 이름'
};
export default MyComponent;
결과화면
음 그러니까 App.js에서 MyComponent 태그 사이에 쓴 문자열을
MyComponent 안에서 출력하려면 props.children 으로 보여줘야한다는거지?
비구조화 할당 문법을 통해 props 내부 값을 추출하기
MyComponent에서 props값을 조회할때 더 편하게 하려고
ES6의 비구조화 할당 문법을 사용하기
MyComponent.js
import React from 'react';
const MyComponent = props => {
const{name, children}=props;
return(
<div>
안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
</div>
);
};
MyComponent.defaultProps ={
name : '비어있는 이름'
};
export default MyComponent;
이 문법은 구조 분해 문법이라고도 불림
함수 파라미터 부분에서도 사용가능함
MyComponent.js
import React from 'react';
const MyComponent = ({name, children}) => {
return(
<div>
안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
</div>
);
};
MyComponent.defaultProps ={
name : '비어있는 이름'
};
export default MyComponent;
이렇게 쓰면 더 편하다는 의미
propTypes 를 통한 props 검증
컴포넌트의 필수 props를 지정하거나 타입을 지정할 때는 propTypes를 사용
MyComponent.js
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({name, children}) => {
return(
<div>
안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
</div>
);
};
MyComponent.defaultProps ={
name : '비어있는 이름'
};
MyComponent.propTypes={
name: PropTypes.string
};
export default MyComponent;
이러면 name 은 모조건 string 형태여야 한다는 의미
string 이 아니어도 값이 나타나기는 하지만 콘솔에 경고 메세지가 출력됨
propTypes 를 지정 안했을 때 경고 메세지를 띄워주는 작업해보기
MyComponent.js
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({name, favoriteNumber, children}) => {
return(
<div>
안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
<br />
제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
};
MyComponent.defaultProps ={
name : '비어있는 이름'
};
MyComponent.propTypes={
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
export default MyComponent;
App.js
import React from 'react';
import MyComponent from './MyComponent';
const App =() => {
return (
<MyComponent name="React" favoriteNumber={1}>
리액트
</MyComponent>
);
};
export default App;
클래스형 컴포넌트에서 props 사용하기
import React, {Component}from 'react';
import PropTypes from 'prop-types';
class MyComponent extends Component{
render(){
const {name, favoriteNumber, children} = this.props;
return(
<div>
안녕하세요, 제 이름은 {name}입니다.<br />
children 값은 {children}
입니다.
<br />
제가 좋아하는 숫자는 {favoriteNumber}입니다.
</div>
);
}
}
MyComponent.defaultProps ={
name : '비어있는 이름'
};
MyComponent.propTypes={
name: PropTypes.string,
favoriteNumber: PropTypes.number.isRequired
};
export default MyComponent;
state
App.js
import React from 'react';
import Counter from './Counter';
const App =() => {
return <Counter />;
};
export default App;
Counter.js
import React, {Component}from 'react';
class Counter extends Component{
constructor(props){
super(props);
//state의 초깃값 설정
this.state = {
number:0
};
}
render(){
const{number}=this.state;//state조회할때에는 this.state로 조회
return(
<div>
<h1>{number}</h1>
<button
//onClick을 통해 클릭되었을 때 호출할 함수 지정
onClick={()=>{
//this.setState로 state에 새로운 값 넣기
this.setState({number:number+1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
state안에 여러 값이 있을 수 있다
Counter.js
import React, {Component}from 'react';
class Counter extends Component{
constructor(props){
super(props);
//state의 초깃값 설정
this.state = {
number:0,
fixedNumber:0
};
}
render(){
const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
return(
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값:{fixedNumber}</h2>
<button
//onClick을 통해 클릭되었을 때 호출할 함수 지정
onClick={()=>{
//this.setState로 state에 새로운 값 넣기
this.setState({number:number+1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
App.js
import React from 'react';
import Counter from './Counter';
const App =() => {
return <Counter />;
};
export default App;
state 초기값 설정 constructor 메서드 선언하지 않고 하기
Counter.js
import React, {Component}from 'react';
class Counter extends Component{
//여기서
state = {
number:0,
fixedNumber:0
};
//여기까지
render(){
const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
return(
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값:{fixedNumber}</h2>
<button
//onClick을 통해 클릭되었을 때 호출할 함수 지정
onClick={()=>{
//this.setState로 state에 새로운 값 넣기
this.setState({number:number+1});
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
this.setState에 객체말고 함수인자 전달
Counter.js
import React, {Component}from 'react';
class Counter extends Component{
//여기서
state = {
number:0,
fixedNumber:0
};
//여기까지
render(){
const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
return(
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값:{fixedNumber}</h2>
<button
//onClick을 통해 클릭되었을 때 호출할 함수 지정
onClick={()=>{
//this.setState로 state에 새로운 값 넣기
this.setState(prevState=>{
return{
number:prevState.number+1
};
});
//위 코드랑 아래 코드는 같은 기능
//함수에서 바로 객체를 반환
this.setState(prevState=>({
number:prevState.number +1
}));
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
App.js
import React from 'react';
import Counter from './Counter';
const App =() => {
return <Counter />;
};
export default App;
버튼 한번 누르면 2씩 증가함
this.setState 끝나고 특정 작업 하기
Counter.js
import React, {Component}from 'react';
class Counter extends Component{
//여기서
state = {
number:0,
fixedNumber:0
};
//여기까지
render(){
const{number,fixedNumber}=this.state;//state조회할때에는 this.state로 조회
return(
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값:{fixedNumber}</h2>
<button
//onClick을 통해 클릭되었을 때 호출할 함수 지정
onClick={()=>{
//this.setState로 state에 새로운 값 넣기
this.setState(
{
number : number + 1
},
() => {
console.log('방금 setState 호출됨');
console.log(this.state);
}
);
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
함수형 컴포넌트에서 useState 사용하기
Say.js
import React, {useState} from'react';
const Say =() =>{
const [message, setMessage]=useState('');
const onClickEnter=()=>setMessage('안녕하세요!');
const onClickLeave=()=>setMessage('안녕히 가세요!');
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1>{message}</h1>
</div>
);
};
export default Say;
App.js
import React from 'react';
import Say from './Say';
const App =() => {
return <Say />;
};
export default App;
한 컴포넌트에서 useState 여러번 사용
import React, {useState} from'react';
const Say =() =>{
const [message, setMessage]=useState('');
const onClickEnter=()=>setMessage('안녕하세요!');
const onClickLeave=()=>setMessage('안녕히 가세요!');
const[color, setcolor] = useState('black');
return (
<div>
<button onClick={onClickEnter}>입장</button>
<button onClick={onClickLeave}>퇴장</button>
<h1 style={{color}}>{message}</h1>
<button style={{color:'red'}} onClick={() => setcolor('red')}>
빨간색
</button>
<button style={{color:'green'}} onClick={() => setcolor('green')}>
초록색
</button>
<button style={{color:'blue'}} onClick={() => setcolor('blue')}>
파란색
</button>
</div>
);
};
export default Say;
state 만들때 배열이나 객체를 업데이트 하려면
배열이나 객체 사본을 만들고
그 사본에 값을 업데이트하고
그 사본의 상태를 setState 혹은 세터 함수를 통해 업데이트 하기
뒤에 더 자세히 나옴