React = SPA ( Single Page Application ) 형태로 동작
- SPA란?
SPA란 Single Page Application의 약자이다.
단일 페이지 어플리케이션(SPA)는 현재 웹개발의 트랜드이다.
기존 웹 서비스는 요청시마다 서버로부터 리소스들과 데이터를 해석하고 화면에 렌더링하는 방식이다. SPA형태는 브라우저에 최초에 한번 페이지 전체를 로드하고, 이후부터는 특정 부분만 Ajax를 통해 데이터를 바인딩하는 방식이다.https://linked2ev.github.io/devlog/2018/08/01/WEB-What-is-SPA/
위처럼 버튼을 Submit 했을 때
window.location.reload()
를 이용해서 페이지를 새로 고침하는 것으로 data를 새로 불러올 수도 있다. 그러나 이는 SPA적이지 못하다.
stateRefresh=()=>{
this.setState({
dateState:[],
completed:0
})
this.callApi()
}
App.js 에서 state를 초기화하고 api를 불러오는 함수를 선언한다.
<CustomerAdd stateRefresh={this.stateRefresh}/>
그리고 props로 값을 넘겨준다.
그리고 submit을 했을 때 받은 props를 호출해준다.
( 원래는 위처럼 addCustomer후에 then을 통해 그 다음에 refresh가 되게 해야되는데 addCustomer를 return을 해주지 않아서 then이 써지지가 않는다 )
그래서 그냥 return만 붙여주면 해결된다. return이 있어야 then을 사용할 수 있다.
import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import Customer from './components/Customer'
import CustomerAdd from './components/CustomerAdd'
import Paper from '@material-ui/core/Paper'
import Table from '@material-ui/core/Table'
import TableHead from '@material-ui/core/TableHead'
import TableBody from '@material-ui/core/TableBody'
import TableRow from '@material-ui/core/TableRow'
import TableCell from '@material-ui/core/TableCell'
import CircularProgress from '@material-ui/core/CircularProgress'
import {withStyles} from '@material-ui/core/styles'
import axios from 'axios'
const styles = theme=>({
root:{
width:'100%',
marginTop: theme.spacing.unit*3,
overflowX:"auto"
},
table:{
minWidth:1080
},
progress:{
margin: theme.spacing.unit *2
}
})
const api = axios.create({
baseURL: `/user/test`
})
class App extends Component{
constructor(props){
super(props)
this.state={
dataState:[],
completed:0
}
}
stateRefresh=()=>{
this.setState({
dateState:[],
completed:0
})
this.callApi()
}
componentDidMount(){
this.timer = setInterval(this.progress,20)
this.callApi()
}
callApi = async()=>{
api.get('/').then(res=>{
this.setState({
dataState:res.data.userData
})
})
}
progress = ()=>{
const{ completed } = this.state.completed
this.setState({
completed: completed>=100 ? 0 : completed +1
})
}
render(){
const {classes} = this.props
return (
<div>
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>번호</TableCell>
<TableCell>이미지</TableCell>
<TableCell>이름</TableCell>
<TableCell>나이</TableCell>
<TableCell>성별</TableCell>
<TableCell>직업</TableCell>
</TableRow>
</TableHead>
<TableBody>
{
this.state.dataState.map(userData=>{
return(
<Customer
img={userData.img}
key={userData.id}
id={userData.idx}
name={userData.name}
gender={userData.gender}
age={userData.age}
job={userData.job}
/>
)
})
}
</TableBody>
<TableBody>
<input type="button" value="get data" onClick={
function(){
api.get('/').then(res=>{
console.log(res.data.userData)
})
}
}></input>
</TableBody>
</Table>
</Paper>
<CustomerAdd stateRefresh={this.stateRefresh}/>
</div>
);
}
}
export default withStyles(styles)(App);
import React, {Component} from 'react'
import axios from 'axios'
const api = axios.create({
baseURL: `/user/test`
})
class CustomerAdd extends Component{
constructor(props){
super(props)
this.state={
name:'',
age:'',
gender:'',
job:'',
file:null, // byte형태의 data
fileName:'' // 이미지의 이름
}
}
handleFormSubmit = (e)=>{
e.preventDefault()
this.addCustomer().then(()=>{
this.props.stateRefresh()
})
this.setState({
name:'',
age:'',
gender:'',
job:'',
file:null, // byte형태의 data
fileName:'' // 이미지의 이름
})
}
handleFileChange = (e)=>{
this.setState({
file: e.target.files[0], // e.target = event가 발생한 input값 자체
fileName: e.target.value
})
}
handleValueChange = (e)=>{
let nextState={}
nextState[e.target.name] = e.target.value
this.setState(nextState)
}
addCustomer = async ()=>{
const formData = new FormData();
formData.append('img',this.state.file)
formData.append('name',this.state.name)
formData.append('age',this.state.age)
formData.append('gender',this.state.gender)
formData.append('job',this.state.job)
const config = {
headers:{
'content-type':'multipart/form-data'
}
}
var object = {}
formData.forEach(function(value,key){
object[key]=value
})
console.log(object)
return api.post('/',
formData,config
)
}
render(){
return(
<form onSubmit={this.handleFormSubmit}>
<h1>고객 추가</h1>
프로필 이미지: <input type="file" name="file" file={this.state.file} value={this.state.fileName} onChange={this.handleFileChange}/><br/>
이름: <input type="text" name="name" value={this.state.name} onChange={this.handleValueChange}/><br/>
나이: <input type="text" name="age" value={this.state.age} onChange={this.handleValueChange}/><br/>
성별: <input type="text" name="gender" value={this.state.gender} onChange={this.handleValueChange}/><br/>
직업: <input type="text" name="job" value={this.state.job} onChange={this.handleValueChange}/><br/>
<button type="submit">추가하기</button>
</form>
)
}
}
export default CustomerAdd;