React 기본 학습 -1. 리액트 입문
리액트 강좌를 보면서 학습한 내용 정리용.
리액트 입문
1. 초기 기입법
리액트js를 불러와서 날코딩할 경우.
<html>
<head>
<!-- 리액트가 동작하는 핵심 코드 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 리액트코드를 웹에 붙여주는 역할 -->
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과 : <div id="root"><button>Like</button></div> -->
<script>
const e = React.createElement;
// 클래스 하나가 컴포넌트 하나
class LikeButton extends React.Component {
constructor(props){
super(props);
this.state = {
liked: false,
};
}
render(){
// 태그를 만들어 주는 함수
return e('button',
{ onClick:() => { this.setState({ liked: true })}, type: 'submit' },
this.state.liked === true ? 'Liked' : 'Like');
// <button onclick="() => { console.log('clicked') }" type="submit">Like</button>
}
}
</script>
<script>
// 리액트로 컴포넌트 만든걸 리액트 돔이 렌더링(화면에 반영)해줌
ReactDOM.render(e(LikeButton), document.querySelector('#root'));
</script>
</body>
</html>
2. 태그 기입법(JSX)
태그 기입법(JSX)(babel 필수)
- 바벨을 이용하면 바벨이 JSX 문법을 createElement 로 변환시켜줌.
- 컴포넌트의 장점 : 원하는 갯수만큼 쉽게 늘릴 수 있다.
<html>
<head>
<!-- 리액트가 동작하는 핵심 코드 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 리액트코드를 웹에 붙여주는 역할 -->
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- javascript 안에 html 문법을 사용하는 등 최신 문법을 사용하기 위해 사용하는것이 babel -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과 : <div id="root"><button>Like</button></div> -->
<script type="text/babel">
class LikeButton extends React.Component {
constructor(props){
super(props);
this.state = {
liked: false,
};
}
render(){
// 컨텐트 부분에 중괄호"{}" 를 감싸주면 내부에서 자바스크립 사용 가능.
return <button type="submit" onClick={() => { this.setState({ liked: true })} }>
{ this.state.liked === true ? 'Liked' : 'Like' }
</button>;
// JSX = Javascript + XML
}
}
</script>
<script type="text/babel">
// 닫는 괄호 필수.
ReactDOM.render(<LikeButton />, document.querySelector('#root'));
// ReactDOM.render(<div><LikeButton /><LikeButton /><LikeButton /><LikeButton /><LikeButton /><LikeButton /><LikeButton /></div>, document.querySelector('#root'));
</script>
</body>
</html>
3. 태그기입법으로 구구단 (Class 이용)
<html>
<head>
<meta charset="UTF-8" />
<title>구구단</title>
<!-- 리액트가 동작하는 핵심 코드 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 리액트코드를 웹에 붙여주는 역할 -->
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- javascript 안에 html 문법을 사용하는 등 최신 문법을 사용하기 위해 사용하는것이 babel -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과 : <div id="root"><button>Like</button></div> -->
<script type="text/babel">
class GuGuDan extends React.Component {
// 바뀌는 속성의 요소는 여기에 넣어줌.
state = {
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
result: '',
};
onSubmit = (e) => {
e.preventDefault();
if (parseInt(this.state.value) == this.state.first * this.state.second) {
this.setState((prevState) => {
return {
result: prevState.value + ' 정답!',
first: Math.ceil(Math.random() * 9),
second: Math.ceil(Math.random() * 9),
value: '',
};
});
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() {
return (
<React.Fragment>
<div>{this.state.first} 곱하기 {this.state.second} 는?</div>
<form onSubmit={this.onSubmit}>
<input ref={ this.onRefInput } type="number" value={this.state.value} onChange={this.onChange} />
<button>입력!</button>
</form>
<div>{this.state.result}</div>
</React.Fragment>
);
}
}
</script>
<script type="text/babel">
// 닫는 괄호 필수.
ReactDOM.render(<GuGuDan />, document.querySelector('#root'));
// ReactDOM.render(<div><LikeButton /><LikeButton /><LikeButton /><LikeButton /><LikeButton /><LikeButton /><LikeButton /></div>, document.querySelector('#root'));
</script>
</body>
</html>
보충설명-1. state 는 변하는 요소를 의미한다
- 해당 컴포넌트 내에서 변하는 항목 (예) 화면 및 처리에 필요한 요소인 name, detail, result 등등)는 state 에 해당한다.
- class 문법의 경우 state는 setState 로 값을 갱신해 주는데 옛날 state로 현재 State를 만들때는 아래와 같이 함수형 setState 를 사용해야 함.
- 옛날 state 를 사용하지 않을 경우에는 함수형 setState 를 사용하지 않아도 무방함.
옛날 state 를 참조하지 않는 setState (문제없음)
- 기존값을 확인하지 않고 값을 갱신하기 때문에 오류(값이 변하지 않은채로 넘어간다거나)가 생길 확률이 있음.
this.setState({ value: '', });
옳지 않은 setState 방법 (옛날 state 를 참조하는데 함수형 setState 가 아님)
- 기존값을 확인하지 않고 값을 갱신하기 때문에 오류(값이 변하지 않은채로 넘어간다거나)가 생길 확률이 있음.
this.setState({ tries: [...tries, { try: value, result: `${strike} 스트라이크, ${ball} 볼입니다.` }], // tries 라는 배열에 예전 tries 배열을 복사에 넣고 추가로 하나 더 배열요소를 더해줌. value: '', });
올바른 setState 방법 (옛날 state(=prevState)를 참조해서 state 를 갱신하는 함수형 setState)
this.setState((prevState) => { // 반드시 이전 값을 받아온 다음 ("(prevState) =>" 부분) 값을 갱신해 준다. return { tries: [...prevState.tries, { try: value, result: `${strike} 스트라이크, ${ball} 볼입니다.` }], value: '', } });
보충설명-2. 화살표함수와 function함수 비교
input.onchange = (e) => { console.log(e.target.value)}
input.onchange = function(e) { console.log(e.target.value) }
- input 태그의
onChange={(e) => this.setState({ value: e.target.value })}
구문은 키보드 입력을 수동으로 반영시키기 위한 구문임. - react 는 Component 를 div로 감싸줘야 하는게 단점 (예) <div>리액트 컴포넌트</div> )
- 쓸모없는 div를 삭제하기 위해서는
<React.Fragment>리액트 컴포넌트</React.Fragment>
와 같이 사용한다. - babel 버젼2 이상부터는 <>리액트 컴포넌트</> 로 대응 가능.
보충설명-3. render() 의 return 기입방식
리액트의 기본적인 기입방식
하지만 이 방식으로 기입하면 나중에 화면에서 표시될때 쓸모없는 div가 너무 많아진다.
render() {
return (
<div>
<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.result}</div>
</div>
);
}
필요없는 div를 삭제하기 위해서 아래와 같이 기입가능.
render() {
return (
<React.Fragment>
<div>{this.state.first} 곱하기 {this.state.second} 는?</div>
<form onSubmit={this.onSubmit}>
<input ref={ this.onRefInput } type="number" value={this.state.value} onChange={this.onChange} />
<button>입력!</button>
</form>
<div>{this.state.result}</div>
</React.Fragment>
);
}
리액트에서는 하나의 컴포넌트가 여러 개의 엘리먼트들을 반환한다.
리액트를 사용하기 위한 문법인 JSX 를 쓸 때, return 문 안에는 반드시 하나의 최상위 태그가 있어야 한다.
이는 리액트가 하나의 컴포넌트만을 리턴할 수 있기 때문이다.
4. 태그기입법으로 구구단 (Hooks 이용)
<html>
<head>
<meta charset="UTF-8" />
<title>구구단</title>
<!-- 리액트가 동작하는 핵심 코드 -->
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<!-- 리액트코드를 웹에 붙여주는 역할 -->
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- javascript 안에 html 문법을 사용하는 등 최신 문법을 사용하기 위해 사용하는것이 babel -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body>
<div id="root"></div> <!-- 결과 : <div id="root"><button>Like</button></div> -->
<script type="text/babel">
// 함수 컴포넌트(Hooks Compoment)
// React.useState(...) 처럼 use 로 시작하는 애들이 Hooks 임.
const GuGuDan = () => {
// 변경이 발생하는 값의 선언
const [first, setFirst] = React.useState(Math.ceil(Math.random() * 9));
const [second, setSecond] = React.useState(Math.ceil(Math.random() * 9));
const [value, setValue] = React.useState('');
const [result, setResult] = React.useState('');
const inputRef = React.useRef(null); // ref
const onChangeInput = (e) => {
setValue(e.target.value);
};
const onSubmitForm = (e) => {
e.preventDefault();
if (parseInt(value) == first * second) {
setResult('정답 : ' + value);
setFirst(Math.ceil(Math.random() * 9));
setSecond(Math.ceil(Math.random() * 9));
setValue('');
// inputRef
inputRef.current.focus();
} else {
setResult('땡');
setValue('');
inputRef.current.focus();
}
};
// 리액트 안에서는 기존의 class -> className, for -> htmlFor 로 기입해야지 해당 속성대로 적용된다.
return (
<React.Fragment>
<div>{first} 곱하기 {second}는?</div>
<form onSubmit={onSubmitForm}>
<input ref={inputRef} onChange={onChangeInput} value={value}/>
<button>입력!</button>
</form>
<div id="result">{result}</div>
</React.Fragment>
);
}
</script>
<script type="text/babel">
// 닫는 괄호 필수.
ReactDOM.render(<GuGuDan />, document.querySelector('#root'));
</script>
</body>
</html>
GitHub : React-Study-1/1.구구단/