module.exports = {
name: 'wordrelay-setting', // 설정의 이름
mode : 'development', // 개발용, 만약 실서비스용이면 : 'production'
devtool : 'eval', // 빠르게 하겠다는 의미
resolve : {
extensions : ['.js', '.jsx'], // 자동으로 js와 jsx 파일을 찾아서 연결해준다.
},
entry : {
app: ['./client'],
}, // 입력 부분
module : {
rules : [{
test: /\.jsx?/,
loader : 'babel-loader',
options : {
presets: ['@babel/preset-env','@babel/preset-react']
}
}]
}, // 모듈 입력
output : {
path : path.join(__dirname, 'dist'), // 현재 폴더 안의 dist 폴더를 말한다.
filename : 'app.js'
}, // 출력 부분
};
위와 같은 설정 파일에서 babel-loader의 presets는 @babel/preset-env와 @babel/preset-react가 있다.
만약 @babel/preset-env에서 설정을 지정할 때는 어떻게 해야할까
@babel/preset-env를 []배열로 감싸고, 이후 설정 정보를 적으면 된다.
presets: [
['@babel/preset-env',{
targets : {
browsers: ['last 2 chrome versions']
}
}],'@babel/preset-react']
presets 부분은 위와 같이 쓸 수 있다.
이전의 구구단과 큰 차이가 없기 때문에 빠르게 코드만 정리하겠다
WordRelay.jsx
const React = require('react');
const { Component } = React;
class WordRelay extends Component {
state = {
word : '김밥말이',
value : '',
result : '',
};
onSubmitForm = e =>{
e.preventDefault();
if(this.state.word[this.state.word.length-1] === this.state.value[0]){
this.setState({
word : this.state.value,
result : '딩동뎅',
value : '',
});
this.input.focus();
}else{
this.setState({
result : '떙',
value : '',
});
this.input.focus();
}
};
onChange = e =>{
this.setState({ value : e.target.value})
};
input;
onRefInput = c =>{
this.input = c;
}
render(){
return(
<>
<div>{this.state.word}</div>
<form onSubmit = {this.onSubmitForm}>
<input ref={this.onRefInput} value={this.state.value} onChange={this.onChange}/>
<button>입력</button>
</form>
<div>{this.state.result}</div>
</>
);
}
}
module.exports = WordRelay;
client.jsx
const React = require('react');
const ReactDom = require('react-dom/client');
const WordRelay = require('./WordRelay');
ReactDom.createRoot(document.querySelector('#root')).render(<WordRelay/>);
webpack.config.js는 이전과 동일
npm i react-refresh @pmmmwh/react-refresh-webpack-plugin -D
npm i -D webpack-dev-server
핫 리로딩용 플러그인와 개발용 웹팩 서버도 다운받아준다.
package.json에 있는 script 부분에 아래와 같이 추가해준다.
"scripts": {
"dev" : "webpack serve --env development"
},
이후 webpack.config.js에서 아래와 같이 불러와준다.
const refresh = require('@pmmmwh/react-refresh-webpack-plugin');
....
....
//plugin 내부에 아래와 같이 사용해준다.
plugins:[
new refresh()
],
이후 babel-loader의 내부 플러그인에도 아래와 같이 플러그인을 넣어준다
plugins :[
'@babel/plugin-proposal-class-properties',
'react-refresh/babel',
],
또한 아까 다운받은 개발용 서버를 넣어준다.
devServer: {
devMiddleware: {
publicPath : '/dist'
},
static:{
directory : path.resolve(__dirname)
},
hot : true,
},
이렇게 되면 총 아래와 같은 코드가 된다.
webpack.config.js
const path = require('path');
// node의 경로 설정을 돕는 도구
const webpack = require('webpack');
const refresh = require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
name: 'wordrelay-setting', // 설정의 이름
mode : 'development', // 개발용, 만약 실서비스용이면 : 'production'
devtool : 'eval', // 빠르게 하겠다는 의미
resolve : {
extensions : ['.js', '.jsx'], // 자동으로 js와 jsx 파일을 찾아서 연결해준다.
},
entry : {
app: ['./client'],
}, // 입력 부분
module : {
rules : [{
test: /\.jsx?/,
loader : 'babel-loader',
options : {
presets: [
['@babel/preset-env',{
targets : {
browsers: ['> 5% in KR','last 2 chrome versions']
}
}],
'@babel/preset-react'
],
plugins :[
'@babel/plugin-proposal-class-properties',
'react-refresh/babel',
],
},
}],
}, // 모듈 입력
plugins:[
new webpack.LoaderOptionsPlugin({ debug: true }),
new refresh()
],
output : {
path : path.join(__dirname, 'dist'), // 현재 폴더 안의 dist 폴더를 말한다.
filename : 'app.js',
publicPath: '/dist',
}, // 출력 부분
devServer: {
publicPath: '/dist',
hot : true,
},
};
이렇게 되면 소스코드의 변경점을 저장한 뒤에 수정 사항을 실시간으로 반영해준다.
최근 react에서는 대부분 hooks 방식을 사용한다. 실제 사용해보면 hooks가 훨씬 간결하고 직관적인 느낌
const React = require('react');
const { useState, useRef} = React;
const WordRelay = ()=>{
const [word, setWord] = useState('김밥말이');
const [value, setValue] = useState('');
const [result, setResult] = useState('');
const inputRef= useRef(null);
const onSubmitForm = e =>{
e.preventDefault();
if(word[word.length-1] === value[0]){
setResult('딩동댕');
setWord(value);
setValue('')
inputRef.current.focus();
}else{
setResult('땡');
setValue('');
inputRef.current.focus();
}
};
const onChangeInput = e =>{
setValue(e.target.value);
};
return(
<>
<div>{word}</div>
<form onSubmit = {onSubmitForm}>
<input ref={inputRef} value={value} onChange={onChangeInput}/>
<button>입력</button>
</form>
<div>{result}</div>
</>
);
}
module.exports = WordRelay;
위에서 핫 리로딩 설정을 해주었기 때문에 빌드를 다시 해주지 않아도 실시간으로 반영된 결과를 볼 수 있다.
input 내에 value와 onchange로 setValue를 해주는 것이 Controlled Input이다.
Uncontrolled Input은 input에 ref만 존재하는 간단한 형태이다.
<form ref={inputRef} >
앞선 onSubmitForm에서 value를 사용하지 않고 e.target으로 모두 대체해주었을 때, input은 간단하게 사용할 수 있다. (권장하지는 않는 방법)