React는 js와 html css로 변환해서 출력해주는 형태
데이터 중심으로 움직인다.
위의 두개 스크립트는 개발용
아래의 두개 스크립트는 배포용 React18버전
<script>
'use strict';
class LikeButton extends React.Component {
constructor(props) {
super(props);
this.state = {liked: fales};
}
render() {
if (this.stat.liked){
return 'You liked this.';
}
return React.createElement('button', {onClick: () => this.setState({liked: true})}, 'Like');
}
}; // ErrorBoundary
const LikeButton = () => {};
function LikeButton() {};
</script>
컴포넌트의 형태
컴포넌트는 데이터와 화면을 하나의 덩어리로 묶어두는 형태
state 가 데이터
render() 의 return 부분이 화면
데이터가 바뀌면 화면이 바뀐다.
화면이 바뀔 부분을 state로 만들어두는 형태
<script>
ReactDOM.render(e(LikeButton), document.querySelector('#root'));
</script>
ReactDOM을 이용해서 컴포넌트를 id="root" 의 안에 출력시키는 형태
return (
<button onClick={()=> this.setState({liked: true})}>
Like
</button>
)
JSX 형태로 return시
onClick 이벤트 핸들러에 화살표 함수를 사용하는 이유는 주로 함수의 스코프와 this 바인딩과 관련이 있음
<script>
ReactDOM.render(<LikeButton/>, document.querySelector('#root'));
</script>
ReactDOM 에서도 코드를 변경해준다
해당방식으로 코드작성시 js가 <> 태그 문법을 이해하지 못한다.
<script type="text/babel">
해결방법으로 바벨문법을사용
return React.createElement('button', {onClick: () => this.setState({liked: true})}, 'Like');
바벨문법 사용시 위의 태그 리턴값을 이런 형태로 인식하게 해준다.
ReactDOM.render(<LikeButton/>, document.querySelector('#root')); // react 17버전 코드
ReactDOM.createRoot(document.querySelector('#root')).render(<LikeButton />); // react 18버전 코드
render와 createRoot를 통해 리액트의 버전을 알 수 있다
React에서는 html태그는 소문자로 시작하고 임의로 생성한 컴포넌트는 대문자로 시작한다.
return (
<button onClick={()=> this.setState({liked: true})} obj={{a: 'b', c: 'd'}}>
{1 + 1}
</button>
)
자바스크립트 코드를 사용시엔 { } 로 감싸줘야한다.
{this.state.liked ? 'Liked' : 'Like!'}
삼항연산자 사용시
JSX에서 if문 사용이 불가능해서 사용
{[1, 2, 3].map((i) => {
return <div>i</div>;
})}
for문을 써야할땐 map을 통해서 사용
return시엔 태그가 하나만 와야한다
태그가 여러개면 <></> 를 사용하거나 다른 태그를 통해서 묶어줘야함
객체를 함부로 바꾸면안됨 (불변성)
onClick={()=> this.setState({liked: true})}
온클릭으로 상태에 대한 변화값을 setState를 통해서 작성하는데 해당부분을
onClick={this.state.liked = true}
이렇게 작성하면 안된다
const array = [];
pop, push, shift, unshift, splice -> 배열을 직접적으로 수정
concat, slice -> 새로운 배열을 만들어냄
react에서는 배열을 직접적으로 수정하는 명령어는 사용하면 안된다.
기존 배열을 복사해서 사용해야함
setState를 통해서 바꿔줌
상태변화를 시각적으로 보면서 하려면 React Developer Tools 을 사용해서 하면 좋음
Profiler는 성능문제를 해결할 때 사용
constructor를 사용하지 않는 코드를 작성하려면
class LikeButton extends React.Component {
state = {liked: false};
onClickButton = () => {
this.setState({liked: true});
}
render() {
if (this.state.liked) {
return 'You liked this.';
}
return (
<button onClick={this.onClickButton}>
{this.state.liked ? 'Liked' : 'Like!'}
</button>
)
}
}
이러한 방식으로 사용할 수 있다
이때 외부로 뺀 onClickButton은 반드시 화살표함수로 작성해야함
this를 사용하는 문제 때문에 class방식은 사용하지 않는편이다.
function LikeButton() {
}
함수 컴포넌트 / (함수형 컴포넌트X)
function LikeButton() {
const [liked, setLiked] = React.useState(false);
if (liked) {
return "You liked this.";
}
return (
<button onClick={() => { setLiked(true); }}>Like</button>
)
}
함수 컴포넌트로 작성한 코드
const [liked, setLiked] = React.useState(false); JS 구조분해 문법
[ 데이터, 데이터를 바꾸는 함수 ] 형태이다
const result = React.useState(false);
const liked = result[0];
const setLiked = result[1];
위의 코드를 풀어쓴 이전코드
배열의 자리에 값을 꺼내서 바로 변수선언을 하는 형태
const [liked, setLiked] = React.useState(false);
const {liked, setLiked} = React.useState(false);
위의 코드는 배열이고 아래는 객체형태이다
return을 한게 결국 화면으로 출력된다.
함수 컴포넌트는 this 를 쓰지않는다
return (
<React.Fragment>
<div>{this.state.first}곱하기{this.state.second}는?</div>
<form onSubmit={this.onSubmit}>
<input type="number" value={this.state.value} onChange={this.onChange} />
<button>입력</button>
</form>
<div>누적 정답 : {this.state.sum}</div>
<div>{this.state.result}</div>
</React.Fragment>
);
Fragment <></> 를 쓸때 오류가 난다면 해당 방식으로 표기해주기
constructor(props) {
super(props);
this.state = {
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
result: '',
sum: 0,
};
}
해당부분에서 constructor를 생략하고 작성가능
state = {
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
result: '',
sum: 0,
};
생략하고 작성한 코드
if (parseInt(this.state.value) === this.state.first * this.state.second) {
this.setState({
result: `정답(${this.state.first} x ${this.state.second} = ${this.state.value})`,
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
sum: this.state.sum + 1,
});
}
위와같은 방식으로 코드를 작성시 this가 이전값을 표기하는지 현재의 값을 표기하는지 헷갈릴 수 있기때문에
if (parseInt(this.state.value) === this.state.first * this.state.second) {
this.setState((prevState) => {
return {
result: `정답(${prevState.first} x ${prevState.second} = ${prevState.value})`,
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
sum: prevState.sum + 1,
};
});
}
해당방식으로 값을 리턴해주면서 preState로 이전값을 표기해준다.
<input type="number" ref={(c) => { this.input = c; }} value={this.state.value} onChange={this.onChange} />
ref를 통해서 DOM에 직접접근 가능
그리고 onSubmit() 안에 this.input.focus()를 작성해서 submit이후에 input태그에 focus가 활성화 되게한다
this.input.focus() == document.queryselector('input')
setState를 할땐 렌더함수가 다시 실행이 된다 ( 글자 하나 입력할때나 버튼클릭할때 등)
함수를 밖에서 선언해서 render의 return부분에 작성하는 이유는
return안에서 실행시 렌더 될때마다 함수가 생성되기 때문
<html>
<head>
<meta charset="utf-8">
<title>web game</title>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
'use strict';
class GuGuDan extends React.Component {
state = {
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
result: '',
sum: 0,
};
onSubmit = (e) => {
e.preventDefault();
if (parseInt(this.state.value) === this.state.first * this.state.second) {
this.setState((prevState) => {
return {
result: `정답(${prevState.first} x ${prevState.second} = ${prevState.value})`,
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
sum: prevState.sum + 1,
};
});
this.input.focus();
} else {
this.setState({
result: '오답',
value: '',
});
this.input.focus();
}
};
onChange = (e) => this.setState({ value: e.target.value });
onRefInput = (c) => { this.input = c };
render() {
console.log("lendering");
return (
<React.Fragment>
<div>{this.state.first}곱하기{this.state.second}는?</div>
<form onSubmit={this.onSubmit}>
<input type="number" ref={this.onRefInput} value={this.state.value} onChange={this.onChange} />
<button type="submit">입력</button>
</form>
<div>누적 정답 : {this.state.sum}</div>
<div>{this.state.result}</div>
</React.Fragment>
);
}
}
</script>
<script type="text/babel">
ReactDOM.createRoot(document.querySelector('#root')).render(<GuGuDan />); // react 18버전 코드
</script>
</body>
</html>
전체코드