MVC(Model View Controller) : 기능 별로 나누어서 구현
Model : 데이터베이스에 작업을 수행하는 Persistance 계층 과 Bussiness Logic을 수행하는 Service 계층을 합친 것
View : 화면 출력 부분
Controller : Model 과 View 사이를 연결
MVC 구조의 View를 독립적으로 구성한 개체
Component를 여러 개 조합해서 하나의 화면을 생성
데이터의 변경이나 이벤트가 발생하면 화면을 리랜더링 하지 않고 Component를 리랜더링 하는 개념
여러가지 기능을 소유하고 있기 때문에 단순한 View 와는 다르다
서버 사이드 템플릿 엔진은 데이터를 출력하는 용도 외에는 사용할 수 없는데 Component 는 여러 가지 기능을 내장한다
함수형 컴포넌트 : 함수를 가지고 생성
클래스형 컴포넌트 : 클래스를 가지고 생성
❓ 함수가 클래스의 인스턴스 보다는 가볍고, 클래스가 함수보다는 안전하다
최근에는 속도 때문에 함수형 컴포넌트를 권장함 - Life Cycle(수명주기) 를 이용하는 경우가 아니라면 함수형 컴포넌트를 사용
기본 틀 - MyComponent.jsx
import React, {Component} from "react";
class MyComponent extends Component{
render(){
return(
<div>
컴포넌트 첫번째
</div>
)
}
}
export default MyComponent
App.js
import logo from './logo.svg';
import './App.css';
import React, {Fragment} from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<MyComponent />
);
}
export default App;
MyComponent.jsx
import React, {Component} from "react";
class MyComponent extends Component{
render(){
const isLoading = true;
if(isLoading){
return <p>Loading...</p>
}
return(
<div>
컴포넌트 첫번째
</div>
)
}
}
export default MyComponent
컴포넌트를 만들 때 이름 = 값의 형태로 설정
클래스 형 컴포넌트에서는 this.props.name 이라는 속성으로 내부에서 사용이 가능
사용하는 이유는 상위 컴포넌트에서 하위 컴포넌트에게 데이터를 전달할 목적
컴포넌트 내부에서 수정할 수 없다.
props 값이 수정되면 자동으로 리렌더링 된다.
App.js 에서 MyComponent 에서 출력하는 부분을 수정
import logo from './logo.svg';
import './App.css';
import React, {Fragment} from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<MyComponent name ="lee" />
);
}
export default App;
import React, {Component} from "react";
class MyComponent extends Component{
render(){
console.log(this.props.name);
return(
<div>
컴포넌트 첫번째 : {this.props.name}
</div>
)
}
}
export default MyComponent
MyComponent.jsx - data 변수
import React, {Component} from "react";
class MyComponent extends Component{
render(){
console.log(this.props.name);
let data = this.props.name;
return(
<div>
컴포넌트 첫번째 : {data}
</div>
)
}
}
export default MyComponent
MyComponent.jsx
class MyComponent extends Component{
render(){
console.log(this.props.name);
//props 의 값을 컴포넌트 내부에서는 변경할 수 없음
//this.props.name = "steven"
//props 의 값을 변경하고자 하면 다른 변수를 생성해서 수행해야 한다
let data = this.props.name;
data = "steven";
return(
<div>
컴포넌트 첫번째 : {data}
</div>
)
}
}
export default MyComponent
props로 전달된 데이터는 함수의 매개변수가 된다.
MyComponent.jsx 파일을 수정해서 함수형 컴포넌트로 변경
MyComponent.jsx
import React, {Component} from "react";
const MyComponent = () => {
return(
<div>함수형 컴포넌트 </div>
)
}
export default MyComponent
MyComponent.jsx
import React, {Component} from "react";
const MyComponent = (props) => { //매개변수로 props 입력
return(
<div>함수형 컴포넌트 : {props.name} </div>
)
}
export default MyComponent
App.js
import logo from './logo.svg';
import './App.css';
import React, {Fragment} from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<MyComponent name ="lee" />
);
}
export default App;
App.js
import logo from './logo.svg';
import './App.css';
import React, {Fragment} from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<MyComponent/>
);
}
export default App;
MyComponent.jsx
import React, {Component} from "react";
const MyComponent = (props) => {
return(
<div>함수형 컴포넌트 : {props.name} </div>
)
}
MyComponent.defaultProps = {
name : "기본값 설정"
}
export default MyComponent
App.js
import logo from './logo.svg';
import './App.css';
import React, {Fragment} from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<>
<MyComponent>태그 안의 내용1</MyComponent>
<MyComponent>태그 안의 내용2</MyComponent>
</>
);
}
export default App;
MyComponent.jsx
import React, {Component} from "react";
const MyComponent = (props) => {
return(
<>
<div>함수형 컴포넌트 : {props.name} </div>
<div>태그 안의 내용 : {props.children}</div>
</>
)
}
MyComponent.defaultProps = {
name : "기본값 설정"
}
export default MyComponent
App.js
import logo from './logo.svg';
import './App.css';
import React, {Fragment} from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<>
<MyComponent>태그 안의 내용1</MyComponent>
<MyComponent>태그 안의 내용2</MyComponent>
</>
);
}
export default App;
MyComponent.jsx
import React, {Component} from "react";
const MyComponent = (props) => {
const {name, children} = props; //구조 분해 할당 내용
return(
<>
<div>함수형 컴포넌트 : {props.name} </div>
<div>태그 안의 내용 : {props.children}</div>
</>
)
}
MyComponent.defaultProps = {
name : "기본값 설정"
}
export default MyComponent
MyComponent.jsx
import React, {Component} from "react";
const MyComponent = ({name,children}) => {
//const {name, children} = props;
return(
<>
<div>함수형 컴포넌트 : {name} </div>
<div>태그 안의 내용 : {children}</div>
</>
)
}
MyComponent.defaultProps = {
name : "기본값 설정"
}
export default MyComponent
MyComponent.jsx
import React from 'react';
import PropTypes from 'prop-types';
const MyComponent = ({name, year, children}) => {
return(
<>
<div>함수형 컴포넌트: {name}</div>
<div>태그 안의 내용: {children}</div>
<div>년도: {year}</div>
</>
)
}
MyComponent.propTypes = {
name:PropTypes.string
}
MyComponent.defaultProps = {
name:"기본값",
year:PropTypes.number.isRequired
}
export default MyComponent;
App.js
import './App.css';
import React from 'react';
import MyComponent from './MyComponent';
function App() {
return (
<MyComponent name='adam' year={2023}>태그 안의 내용</ MyComponent>
);
}
export default App;
array : 배열
bool : boolean
func : 함수 - 자바스크립트에서는 함수도 하나의 자료형
number : 숫자
object : 객체
string : 문자열
node : 화면에 출력될 수 있는 모든 것
element : react 요소
any : 모든 자료형
App.js
import MyComponent from './MyComponent';
function App() {
return (
<>
<MyComponent name="아담" favoriteNumber={3} children="my son"/>
</>
)
}
export default App;
MyComponent.jsx
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;
All React Component must act like pure functions with respect to their props
모든 react component는 그들의 props에 관해서는 Pure 함수 같은 역할
props 는 상위 컴포넌트가 하위 컴포넌트에게 넘겨주는 데이터 - 데이터를 상위 컴포넌트에서 만들기 때문에 하위 컴포넌트에서 변경하지 못하도록 함
state 는 컴포넌트 내부에서 만드는 데이터로 읽기와 수정 모두 가능
초기화
get
set
App.js
import MyComponent from './MyComponent';
import ClassComponent from './ClassComponent';
function App() {
return (
<>
<ClassComponent/>
<MyComponent name="아담" favoriteNumber={3} children="my son"/>
</>
)
}
export default App;
ClassComponent.jsx
import React, { Component } from "react";
class ClassComponent extends Component{
//생성자
constructor(props){
super(props);
this.state = {
number:0
}
}
render(){
return(
<>
<p>number:{this.state.number}</p>
<button onClick={()=>{
this.setState({
number: this.state.number + 1
})
}}>증가</button>
</>
)
}
}
export default ClassComponent;
실행을 해서 버튼을 누르면 숫자가 증가하면서 출력된다
react 에서는 props 나 state 값을 직접 변경하는 것이 허용되지 않는다
props 나 state 는 변경할 수 없는 데이터로 만들어 진 것(Virtual DOM)
변경하고자 하면 다른 곳에 복제를 해서 변경을 해야한다.
생성자가 아닌 메서드 외부애서 생성해도 인스턴스가 소유하기 때문에 성자에서 생성한 것 과 같은 효과를 가짐
ClassComponent.jsx
import React, { Component } from "react";
class ClassComponent extends Component{
//생성자
/*
constructor(props){
super(props);
this.state = {
number:0
}
}
*/
// 생성자가 아닌 메서드 외부애서 생성해도 인스턴스가 소유하기 때문에
// 생성자에서 생성한 것 과 같은 효과를 가짐
state = {
number:1
}
render(){
return(
<>
<p>number:{this.state.number}</p>
<button onClick={()=>{
this.setState({
number: this.state.number + 1
})
}}>증가</button>
</>
)
}
}
export default ClassComponent;
setState 에는 state 수정 구문을 삽입하는데 수정 구문 대신에 함수를 대입해도 가능
함수는 state 를 매개변수로 받고 state 의 수정 구문을 return 해주면 된다.
ClassComponent.jsx 파일의 button 생성 코드 수정
ClassComponent.jsx
import React, { Component } from "react";
class ClassComponent extends Component{
//생성자
/*
constructor(props){
super(props);
this.state = {
number:0
}
}
*/
// 생성자가 아닌 메서드 외부애서 생성해도 인스턴스가 소유하기 때문에
// 생성자에서 생성한 것 과 같은 효과를 가짐
state = {
number:1
}
render(){
return(
<>
<p>number:{this.state.number}</p>
<button onClick={()=>{
this.setState(
(prevState) => {return {number:prevState.number + 1}}
)
}}>증가</button>
</>
)
}
}
export default ClassComponent;
<동기 VS 비동기 >
동기 (Synchronous)
- 순차적으로 실행, 하나의 명령이 종료된 후 다른 명령을 수행
- 앞의 작업이 끝나야 다음 작업이 수행되는 구조라서 앞의 작업이 끝나고 난 후 작업을 수행하거나 결과를 사용하고자 하는 것이 어렵지 않음(결과를 리턴)
비동기 (ASynchronous)
- 하나의 명령이 수행 중인 동안에 다른 명령을 수행할 수 있는 방식 - 스레드
- 현재 작업이 끝나고 난 후 수행되는 코드를 만들 때는 콜백을 사용하거나 Promise 또는 async & await 구문을 활용
- 콜백을 사용할 때는 매개변수를 잘 파악해야 한다
- 매개변수가 작업의 결과인 경우가 많음
setState 로 state 를 변경하고 난 후 호출되는 콜백을 사용하고자 할 때는 setState 의 두번째 매개변수로 함수를 대입하면 된다.
ClssComponent 에서 state 의 변화가 생기고 난 후 호출되는 코드 작성
ClassComponent.jsx
import React, { Component } from "react";
class ClassComponent extends Component{
//생성자
/*
constructor(props){
super(props);
this.state = {
number:0
}
}
*/
// 생성자가 아닌 메서드 외부애서 생성해도 인스턴스가 소유하기 때문에
// 생성자에서 생성한 것 과 같은 효과를 가짐
state = {
number:1
}
render(){
return(
<>
<p>number:{this.state.number}</p>
<button onClick={()=>{
this.setState(
(prevState) => {return {number:prevState.number + 1}}, //상태 변하는 문장 뒤에 , 입력 후 함수 작성
() =>{console.log("상태 변화 발생!!!!");}
)
}}>증가</button>
</>
)
}
}
export default ClassComponent;
state 는 setState 메서드로만 수정해야 하고 객체 나 배열을 수정하고자 하는 경우는 복사본을 만들고 복사본을 수정한 후 그 복사본을 setState에 대입해서 업데이트 해야한다
배열이나 문자열의 경우 메서드가 원본에 작업을 수행하는지, 아니면 복사본에 수행한 후 리턴하는지 확인을 해볼 필요가 있다
import React, { Component } from "react";
class ClassComponent extends Component{
//생성자
/*
constructor(props){
super(props);
this.state = {
number:0
}
}
*/
// 생성자가 아닌 메서드 외부애서 생성해도 인스턴스가 소유하기 때문에
// 생성자에서 생성한 것 과 같은 효과를 가짐
state = {
number:1
}
render(){
return(
<>
<p>number:{this.state.number}</p>
<button onClick={()=>{
this.setState(
(prevState) => {return {number:prevState.number + 1}}, //상태 변하는 문장 뒤에 , 입력 후 함수 작성
() =>{
console.log("상태 변화 발생!!!!");
let ar = ["a","b","c"];
//원본을 변경하는 메서드
ar.push("d");
console.log(ar);
}
)
}}>증가</button>
</>
)
}
}
export default ClassComponent;
import React, { Component } from "react";
class ClassComponent extends Component{
//생성자
/*
constructor(props){
super(props);
this.state = {
number:0
}
}
*/
// 생성자가 아닌 메서드 외부애서 생성해도 인스턴스가 소유하기 때문에
// 생성자에서 생성한 것 과 같은 효과를 가짐
state = {
number:1
}
render(){
return(
<>
<p>number:{this.state.number}</p>
<button onClick={()=>{
this.setState(
(prevState) => {return {number:prevState.number + 1}}, //상태 변하는 문장 뒤에 , 입력 후 함수 작성
() =>{
console.log("상태 변화 발생!!!!");
let ar = ["a","b","c"];
//원본을 변경하는 메서드
ar.push("d");
console.log(ar);
// 요소를 순회하면서 함수를 수행해서 그 결과를
// 가지고 새로운 배열을 만들어서 리턴하는 함수
console.log(ar.map((e)=>{return e + "알파벳"}));
}
)
}}>증가</button>
</>
)
}
}
export default ClassComponent;
<div class = 'outer'>
<div class = 'inner'>
</div>
</div>
outer와 inner 모두에 click에 대한 이벤트 처리 핸들러가 존재하는 경우 inner에서 click이 발생하면 inner의 click에 해당하는 event handler를 수행 한 후 outer의 click에 해당하는 event handler를 수행하는 것이 event bubbling
event bubbling 을 막고자 할 때는 Event 객체가 stopPropagation()을 호출하면 된다.
Input 에 입력된 값은 value 속성에 저장
이벤트 처리를 수행할 Component를 생성 - EventComponent.jsx
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type="text" placeholder="이름을 입력해주세요"/>
</>
)
}
}
export default EventComponent;
App.js
import MyComponent from './MyComponent';
import ClassComponent from './ClassComponent';
import EventComponent from './EventComponent';
function App() {
return (
<>
<EventComponent/>
<ClassComponent/>
<MyComponent name="아담" favoriteNumber={3} children="my son"/>
</>
)
}
export default App;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type="text" placeholder="이름을 입력해주세요"
onChange={(e)=>{
//입력하는 내용을 콘솔에 출력
console.log(e.target.value);
}}/>
</>
)
}
}
export default EventComponent;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
constructor(props){
super(props);
this.state = {
name:''
}
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type="text" placeholder="이름을 입력해주세요"
value={this.state.name}
onChange={(e)=>{
//입력하는 내용을 콘솔에 출력
//console.log(e.target.value);
//입력된 값을 name 에 저장
this.setState({
name:e.target.value
})
}}/>
</>
)
}
}
export default EventComponent;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
constructor(props){
super(props);
this.state = {
name:''
}
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type="text" placeholder="이름을 입력해주세요"
value={this.state.name}
onChange={(e)=>{
//입력하는 내용을 콘솔에 출력
//console.log(e.target.value);
//입력된 값을 name 에 저장
this.setState({
name:e.target.value
})
}}/>
<button onClick={(e)=>{
alert(this.state.name);
this.setState({
name:''
})
}}>버튼</button>
<input type='button' value = '버튼'/>
</>
)
}
}
export default EventComponent;
이벤트 처리의 내용이 많으면 DOM 생성 태그 안에 많은 양의 자바스크립트 코드를 작성하면 가독성이 떨어지게 되고, 공유 데이터를 핸들링하는 경우에 대부분의 경우 공유 데이터는 App.js 에 존재할 가능성이 높은데,
이 경우 App.js 에 함수를 만들어 처리하는 것이 수월하므로 App.js나 상위 컴포넌트에서 이벤트 처리 함수를 만들어서 하위 컴포넌트에게 전달하는데 이 경우는 함수를 연결하는 형태로 이벤트를 처리하게 된다.
동일한 내용을 별도의 함수로 만들어서 처리
클래스 내의 함수에서 this 를 사용하고자 하는 경우 화살표 함수를 만들면 안됨
let f = function(){
내용
this.
}
// 화살표 함수에서는 this 와 arguments를 사용할 수 없다
let f = () =>{
내용
this.
}
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
//input 의 내용이 변경될 때 호출될 함수
handleChange(e){
this.setState({
name:e.target.value
})
}
//버튼을 클릭했을 때 호출 될 함수
handleClick(e){
alert(this.state.name);
this.setState({
name:''
})
}
constructor(props){
super(props);
this.state = {
name:''
}
// 같은 클래스에 속했다고 해서 아래에서 불러올 수 없다
// 클래스의 구조일분 인스턴스의 구조는 아니기 때문
this.handleClick = this.handleClick.bind(this);
this.handleChange = this.handleChange.bind(this);// 이 구문 매우 중요
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type="text" placeholder="이름을 입력해주세요"
value={this.state.name}
onChange={this.handleChange}/>
<button onClick={this.handleClick}>버튼</button>
<input type='button' value = '버튼'/>
</>
)
}
}
export default EventComponent;
리액트는 바벨이 크로스 컴파일링 (ECMA 2015+ 이상의 문법으로 작성된 스크립트 코드를 하위 버전에 호환될 수 있게 변환)을 수행해주는데 클래스 안에 만든 요소를 클래스 안에서 this를 이용해서 접근할 수 있도록 지원
앞의 컴포넌트를 수정 - 이제 바인딩 작업이 필요없다
생성자에서 변환하는 작업을 안할 수 있음
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
//input 의 내용이 변경될 때 호출될 함수
state = {
name: ''
}
handleChange = (e) => {
this.setState({
name:e.target.value
})
}
//버튼을 클릭했을 때 호출 될 함수
handleClick = (e) => {
alert(this.state.name);
this.setState({
name:''
})
}
constructor(props){
super(props);
this.state = {
name:''
}
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type="text" placeholder="이름을 입력해주세요"
value={this.state.name}
onChange={this.handleChange}/>
<button onClick={this.handleClick}>버튼</button>
<input type='button' value = '버튼'/>
</>
)
}
}
export default EventComponent;
하나의 여러 가지 이벤트 또는 여러 객체의 동일한 이벤트를 하나의 객체 또는 함수를 가지고 처리하는 것
유사한 이벤트 처리를 위해서 함수를 여러 개 만들거나 객체를 여러 개 만드는 것도 자원의 낭비
Event Routing 을 하게 되면 이벤트가 발생한 객체를 구분할 수 있어야 하는데 자바스크립트 에서는 DOM객체를 찾아서 비교하지만, 리액트에서는 name 속성에 값을 부여한 후 e.target.name 속성을 가지고 구분한다 HTML 의 DOM 만 사용하는 것이 아니므로 id속성을 이용해서 DOM 을 찾는 것을 권장하지 않음
리액트를 하다 보면 아래와 같은 코드는 보이지 않음
이전 컴포넌트를 수정 - input을 2개로 늘릴 것임
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
//input 의 내용이 변경될 때 호출될 함수
state = {
name: '',
age: ''
}
handleNameChange = (e) =>{
this.setState({
name:e.target.value
})
}
handleAgeChange = (e) =>{
this.setState({
age:e.target.value
})
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type='text' value = {this.state.name} //전달 - value
placeholder='이름 입력' onChange={this.handleNameChange}/>
<input type='text' value={this.state.age}
placeholder='나이 입력' onChange={this.handleAgeChange}/>
<button>확인</button>
</>
)
}
}
export default EventComponent;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
//input 의 내용이 변경될 때 호출될 함수
state = {
name: '',
age: ''
}
handleNameChange = (e) =>{
this.setState({
name:e.target.value
})
}
handleAgeChange = (e) =>{
this.setState({
age:e.target.value
})
}
handleClick = (e) => {
alert(this.state.name + ':' + this.state.age);
this.setState({
name : '',
age : ''
})
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type='text' value = {this.state.name} //전달 - value
placeholder='이름 입력' onChange={this.handleNameChange}/>
<input type='text' value={this.state.age}
placeholder='나이 입력' onChange={this.handleAgeChange}/>
<button onClick={this.handleClick}>확인</button>
</>
)
}
}
export default EventComponent;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
//input 의 내용이 변경될 때 호출될 함수
state = {
name: '',
age: ''
}
handleChange = (e) =>{
// 이벤트가 발생한 객체의 이름과 동일한 state 의 값을
// 입력한 내용으로 수정
this.setState({
[e.target.name]:e.target.value
})
}
handleClick = (e) => {
alert(this.state.name + ':' + this.state.age);
this.setState({
name : '',
age : ''
})
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type='text' value = {this.state.name} name = 'name' //전달 - value
placeholder='이름 입력' onChange={this.handleChange}/>
<input type='text' value={this.state.age} name = 'age'
placeholder='나이 입력' onChange={this.handleChange}/>
<button onClick={this.handleClick}>확인</button>
</>
)
}
}
export default EventComponent;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
//input 의 내용이 변경될 때 호출될 함수
state = {
name: '',
age: ''
}
handleChange = (e) =>{
// 이벤트가 발생한 객체의 이름과 동일한 state 의 값을
// 입력한 내용으로 수정
this.setState({
[e.target.name]:e.target.value
})
}
handleClick = (e) => {
alert(this.state.name + ':' + this.state.age);
this.setState({
name : '',
age : ''
})
}
// input의 KeyPress 이벤트 연결할 함수
handleKeyPress = (e) => {
//alert(e.key) //그냥 확인하는 방법
//누른 키가 Enter 라면 handleClick 함수를 호출
//이벤트를 강제로 발생시키는 것을 Event - Trigger 라고 한다
if(e.key === 'Enter'){
this.handleClick();
}
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type='text' value = {this.state.name} name = 'name' //전달 - value
placeholder='이름 입력' onChange={this.handleChange}/>
<input type='text' value={this.state.age} name = 'age'
placeholder='나이 입력' onChange={this.handleChange} //나이 입력에 onKeyPress 적용
onKeyPress={this.handleKeyPress}/>
<button onClick={this.handleClick}>확인</button>
</>
)
}
}
export default EventComponent;
input 의 defaultValue 나 defaultChecked 속성을 이용하면 기본값이나 기본 체크를 설정할 수 있다.
file 은 보안 문제 때문에 value 값을 가져오는 것은 가능하지만 value를 설정하는 것은 안된다.
checkbox의 체크 여부를 가져오고자 하는 경우에는 e.target.checked 로 가져오면 된다.
file
이벤트가 발생했을 때 이 이벤트와 관련된 웹 브라우저의 기본 구현 내용을 실행하지 않도록 해주는 함수
form 의 submit 이벤트는 form의 데이터를 action으로 설정한 곳으로 전송하는 기능을 내장하고 있고 form 의 reset 이벤트는 form의 데이터를 삭제하는 기능을 내장하고 있으며 브라우저는 DragAndDrop 이벤트 발생 시 drop 을 막아버리는 기능을 내장하고 있음
웹에서 입력할 수 있는 도구
- input : text, passwd, checkbox, radio,
file, hidden(보이지는 않는 속성이지만 서버에게 데이터를 전달하고자 하는 경우 사용)
, image, button, submit, reset
<checkbox 와 radio 는 하나의 그룹이 되려면 name의 값이 같아야 하고,
value를 설정해주는 것이 좋다
value 설정이 안되어 있으면 on 이나 off 가 서버에게 전송되고
value 가 설정되어 있으면 value가 넘어간다>
- textarea : 여러 줄의 문자열, 태그 와 태그 사이에 내용이 들어가기 때문에
설정을 할 때에는 value 가 아니고 innerHTML 이고 입력된 내용을 가져올 때는 value
여는 태그 와 닫는 태그의 라인이 다르면 첫 커서가 중간에 들어간다
- select : 목록 중에 하나를 선택
select 에 name 을 설정하고 option 으로 항목을 만드는데
value를 설정해줘야 함
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
state={
name:'',
content:'',
image: []
}
handleChange = (e) => {
this.setState({
[e.target.name]:e.target.value
})
}
handleClick = (e) => {
alert(this.state.name + '+' + this.state.content);
console.log(this.state.image);
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type='text' name = 'name' defaultValue='No Name'
onChange={this.handleChange} />
<br />
<fieldset>
<legend>성별</legend>
<input type='radio' name = 'gender' value='man'defaultChecked/>남자
<input type='radio' name = 'gender' value='woman'/>여자
</fieldset>
<textarea name='content' onChange = {this.handleChange}></textarea>
<select name='cnt'>
<option value = '1'>1</option>
<option value = '2'>2</option>
<option value = '3'>3</option>
</select>
<input type='file' name='image' multiple='multiple'
accept='iamge/*' onChange={this.handleChange}/>
<br/>
<button onClick={this.handleClick}>전송</button>
</>
)
}
}
export default EventComponent;
EventComponent.jsx
import React, {Component} from "react";
class EventComponent extends Component{
state={
image: []
}
//파일의 경우는 files 속성을 state 에 연결해야 한다
//file 의 경우는 e.target.value 를 호출하면 파일의 절대경로를 문자열로 리턴
//이 데이터는 서버로 전송하면 문자열이 된다.
handleChange = (e) => {
this.setState({
[e.target.name]:e.target.files
})
}
handleClick = (e) => {
console.log(this.state.image);
}
render(){
return(
<>
<h1>이벤트 연습</h1>
<input type='file' name='image' multiple='multiple'
accept='iamge/*' onChange={this.handleChange}/>
<br/>
<button onClick={this.handleClick}>전송</button>
</>
)
}
}
export default EventComponent;
브라우저는 Drag 이벤트가 발생할 때 Drop 이벤트를 중지시키는 기보 기능을 내장하고 있음
Drop 이벤트를 사용하고자 할 때는 첫 번째 문장이 e.preventDefault()가 되어야 한다.