컴포넌트를 선언하는 방식은 두가지이다
하나는 함수 컴포넌트, 다른하나는 클래스 컴포넌트이다
1. 클래스형 컴포넌트
import { Component } from 'react';
import './App.css';
class App extends Component {
render() {
const name = 'react';
return <div className="react">{name}</div>;
}
}
export default App;
클래스 컴포넌트에서는 render 함수가 꼭있어야한다.
그렇다면 함수 컴포넌트와 클래스컴포넌트는 어떨때 사용해야할까?
함수 컴포넌트의 단점은 state와 라이프사이클 API의 사용이 불가능하다
이단점은 리액트 버젼 16.8이후 Hooks라는 기능이 도입되어서 해결되었다.
리액트 공식 매뉴얼에서는 컴포넌트를 새로 작성할때 함수 컴포넌트, Hooks를 사용하도록 권장하고있다
앞으로 초반에 기능구현할땐 클래스형 컴포넌트 위주로 리액트 기본기를 익히고, 후반부에는 Hooks를 완벽히 이해한후
함수 컴포넌트와 Hooks를 기반으로 컴포넌트를 작성하겠다
2. 첫 컴포넌트 생성
1. 컴포넌트 생성하기
src 폴더안에 MyComponent.js 파일을 만들다
const MyComponent = () => {
return <div>처음만들어보는 컴포넌트</div>;
};
export default MyComponent;
새로운 컴포넌트를 만들었다
2. 모듈 내보내기 및 불러오기
위에있는 export default MyComponent로 모듈을 export했다
import { Component } from 'react';
import './App.css';
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent></MyComponent>;
};
export default App;
import로 모듈을 import한후
MyComponent로 해당 컴포넌트를 불러왔다.
3. props
1. 컴포넌트 사용시 prop값 지정하기
props는 properties를 줄인 표현으로 컴포넌트 속성을 설정할 때 사용하는 요소이다.
부모컴포넌트에서 prop를 설정하고, 자식컴포넌트에서 렌더링해서 보여줄수있습니다.
App.js
import { Component } from 'react';
import './App.css';
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent name="yunrap"></MyComponent>; //속정 name에 설정
};
export default App;
MyComponent.js
const MyComponent = (props) => {
return <div>안녕하세요 {props.name}입니다.</div>;
};
export default MyComponent;
props로 받아와서 .을 사용해서 해당 props에 접근할수있습니다.
2. props 기본값 설정: defaultProps
부모컴포넌트에서 prop를 지웠을때 기본으로 설정하고싶은 props는
컴포넌트이름.defaultProps로 설정해줄수있다
const MyComponent = (props) => {
return <div>안녕하세요 {props.name}입니다.</div>;
};
MyComponent.defaultProps = {
name: 'yunrap',
};
export default MyComponent;
3. 태그 사이의 내용을 보여주는 children
컴포넌트 태그 사이의 내용을 보여주고싶을때 children을 사용한다
App.js
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent>리액트</MyComponent>;
};
export default App;
MyComponent.js
const MyComponent = (props) => {
return (
<div>
안녕하세요, 제이름은 {props.name}입니다.
<br />
chidren의 값은 {props.children}입니다.
</div>
);
};
MyComponent.defaultProps = {
name: 'yunrap',
};
export default MyComponent;
4. destruction assignment 문법을 통한 props 내부값추출
props키워드 없이 바로 해당 props를 조회하려면
ES6 의 destruction assignment(비구조화)문법을 사용하여 내부값을 바로 추출할수있다.
const MyComponent = (props) => {
const { name, children } = props;
return (
<div>
안녕하세요, 제이름은 {name}입니다.
<br />
chidren의 값은 {children}입니다.
</div>
);
};
MyComponent.defaultProps = {
name: 'yunrap',
};
export default MyComponent;
이렇게 파라미터에 바로 destruction assignment를 사용할수있다.
const MyComponent = ({ name, children }) => {
return (
<div>
안녕하세요, 제이름은 {name}입니다.
<br />
chidren의 값은 {children}입니다.
</div>
);
};
MyComponent.defaultProps = {
name: 'yunrap',
};
export default MyComponent;
5. propTypes를 통한 props검증
컴포넌트의 필수 props를 지정하거나, 타입을 지정할때는 propTypes를 사용한다
App.js
import MyComponent from './MyComponent';
const App = () => {
return <MyComponent name={3}>리액트</MyComponent>;
};
export default App;
MyComponent.js
import PropsTypes from 'prop-types';
const MyComponent = ({ name, children }) => {
return (
<div>
안녕하세요, 제이름은 {name}입니다.
<br />
chidren의 값은 {children}입니다.
</div>
);
};
MyComponent.defaultProps = {
name: 'yunrap',
};
MyComponent.PropsTypes = {
name: PropsTypes.string, //문자열만 허용한다
};
export default MyComponent;
6. isRequired를 사용하여 필수 propTypes 설정
이거부분 재수정....
4. state
리액트에서 state는 컴포넌트 내부에서 바뀔수있는 값을 의미한다
만약 props를 바꾸려면 부모컴포넌트에서 바꿔야한다
리액트에는 두가지종류의 state가 있다
하나는 클래스형 컴포넌트 state와, 함수컴포넌트의 useState라는 함수를 통해 사용하는 state이다.
1. 클래스형 컴포넌트의 state
import { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props); // Component가 가진 생성자 함수를 호출
// state의 초기값 설정하기 (객체형식)
this.state = {
number: 0,
};
}
render() {
const { number } = this.state; // state를 조회할때는 this.state로 조회한다
return (
<div>
<h1>{number}</h1>
<button
//onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
onClick={() => {
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
app.js
import Counter from './Counter';
import MyComponent from './MyComponent';
const App = () => {
return <Counter></Counter>;
};
export default App;
그후 컴포넌트를 렌더링해주면 카운터가 증가하는
props가변경되는 클래스형컴포넌트가 가지고있는 state를 사용해봤다
2. state 객체 안에 여러값이있을때
import { 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({ number: number + 1 }); //변하는값만 설정
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
this.setState안에는 새롭게 변하는값들을 보통 설정해준다
3. state constructor에서 꺼내기
constructor를 사용하지않고 state를 초깃값으로 설정해서 사용할수있습니다.
import { 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({ number: number + 1 }); //변하는값만 설정
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
4. this.setState에 객체 대신 함수 인자 전달하기
만약 함수내부에서 this.setState를 두번 호출하면 어떻게 될까?
onClick={() => {
this.setState({ number: number + 1 }); //변하는값만 설정
this.setState({ number: this.state.number + 1 });
}}
this.setState를 사용한다고 해서 바로 state값이 바뀌지않는다
이에대한 해결책은 this.setState를 사용할때 객체 대신에 함수를 인자로 넣어준다
import { 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((prevState) => {
return { number: prevState.number + 1 };
}); //변하는값만 설정
this.setState((prevState) => ({ number: prevState.number + 1 }));
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
여기서
this.setState((prevState) => ({ number: prevState.number + 1 }));
(prevState) => ({ }) 이문법을 사용하여 화살표 함수에서 바로 객체를 반환하도록 하였다.
5. useState 사용하기
useState 함수의 인자에는 (현재상태, 상태를바꾸어주는함수) 이 형식으로 사용한다
import { 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;
여기서
const [message, setMessage] = useState('');
이문법은 배열 비구조화로
const message = useState(' ');
const setMessage = useState(' ');
이방법으로 사용한다
6. 한 컴포넌트에서 useState 여러번 사용하기
useState는 한 컴포넌트에서 여러번 사용해도 상관없다.
import { 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: 'blue' }} onClick={() => setColor('blue')}>
파란색
</button>
<button style={{ color: 'black' }} onClick={() => setColor('black')}>
검은색
</button>
</div>
);
};
export default Say;
5. state를 사용할때 주의사항
1. state값을 바꾸어야할때는 setState혹은 useState를 통해 값꿀수있습니다
즉
const[object, setObject] = useState({a:1 , b:2});
object.b = 2; 이렇게 사용하면 잘못된 코드입니다.
그렇다면 배열이나, 객체를 업데이트하려면 어떻게해야할까?
* 객체, 배열 값을 업데이트할때
const object = {a:1, b:2, c:3};
const nextObject = {...object, b:2} // 사본을 만들어서 b값만 덮어쓰기
//배열 다루기
const array = [
{id:1, value: true},
{id:2, value: true},
{id:3, value: false}
];
let nextArray = array.concat({id:4}); // 새항목추가
nextArray.filter(item => item.id !==2 ); // id가 2인항목 제거
nextArray.map(item => (item.id === 1 ? {...item, value:false } : item));
// id가 1인항목의 value를 false로 설정
여기까지 state를 다루기위한 클래스 컴포넌트와 함수컴포넌트의 useState에대해 알아보았다
다음장엔 이벤트 핸들링을 볼것이다
'Book' 카테고리의 다른 글
[리액트를 다루는 기술] 6. ref: DOM에 이름달기 (0) | 2022.07.03 |
---|---|
[리액트를 다루는 기술] 5. 이벤트 핸들링 (0) | 2022.07.02 |
[리액트를 다루는 기술] 3. 코드이해하기 (0) | 2022.06.26 |
[리액트를 다루는 기술] 2. 작업 환경 설정 (0) | 2022.06.26 |
[리액트를 다루는 기술] 1. 왜 리액트인가? (0) | 2022.06.26 |