React 동빈나 강좌 #10

ims·2020년 8월 18일
0

React

목록 보기
10/25

State 변경을 통한 reload

React = SPA ( Single Page Application ) 형태로 동작

  1. SPA란?
    SPA란 Single Page Application의 약자이다.
    단일 페이지 어플리케이션(SPA)는 현재 웹개발의 트랜드이다.
    기존 웹 서비스는 요청시마다 서버로부터 리소스들과 데이터를 해석하고 화면에 렌더링하는 방식이다. SPA형태는 브라우저에 최초에 한번 페이지 전체를 로드하고, 이후부터는 특정 부분만 Ajax를 통해 데이터를 바인딩하는 방식이다.

    https://linked2ev.github.io/devlog/2018/08/01/WEB-What-is-SPA/

SPA의 구현 방식 =

부모 component에서 자식 component로 함수를 props형태로 건네주는 방식으로 구현한다.

위처럼 버튼을 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을 사용할 수 있다.

App.js 코드

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);

CustomerAdd.js

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;
profile
티스토리로 이사했습니다! https://imsfromseoul.tistory.com/ + https://camel-man-ims.tistory.com/

0개의 댓글