-
[React] 리액트 프로젝트 사용 기술 정리기타/FE 2020. 6. 9. 15:57반응형
React 프로젝트
사용한 기술 및 라이브러리
생겼던 문제들
이미지 용량 nginx
이모티콘 utf 처리
timezone
0. 기본 레이아웃 및 큰 컴포넌트
index/Root/App에서 Login or Dashboard로
0-1. React-router-dom
// Root.js import {BrowserRouter} from “ React-router-dom “ <BrowserRouter> <App/> </BrowserRouter>
Q) 이렇게 한 이유 + react-router-dom이란? react, react-dom, reat-router-dom
Q) 컴포넌트란 ??리액트란??
Q) 리액트 기본 구조 이해하기
Class hello extend Component{ render(){ return(); } } export default hello
0-2. axios.defaults.baseURL='http://localhost:8080';
baseURL 제일 밖으로 빼놓음
0-3. index.js에서
serviceWorker.unregister();
이걸 resgister로 하면 서버 캐시 지워서 새로 들어갈때까지 이전 프로젝트 변경 전 모습으로 남아있음
Q) servicework - register, unregister란?
1. 로그인 컴포넌트 ( 대시보드 밖/ 안 따로 )
대시보드 밖 ( 로그인 전, storage에 token없음)
sign/Login
----/Logout
Q) sessionstorage, localstorage란? 나는 왜 토큰 session에 했지..?
Q) event.preventDefault()란?
이메일, 비밀번호 입력받아서 event.target.[name].value 에 따라서 focus()해주거나 검사하거나 ,, 로그인해주거나 함
axios.post로 formdata에 email, password값 보내고 token얻어와 sessionstorage에 저장하고 url /로 보내줌
Q)axios란? .then .catch란?
Q)this.props.history.push란?
Q)error.response status ,,
sign/PasswordUpd
----/signup
----/userList
----/CheckAuth
----/info
----/infoUpd
회원가입은 pw.match(정규식)이렇게 양식 비교해보고 중복확인은 버튼 누르면 check api보내는식으로 함
Q) react에 onchange, onclick, => handlechange, handleclick 바닐라자바스크립트로도 생각해보기
2. 관리자페이지 Dashboard
2.1 토큰검증
axios.interceptors.request.use( config => { if(config.url.match("dapi.kakao.com")){ config.headers['Authorization'] = 'KakaoAK '; } else{ const token = window.sessionStorage.getItem("jwtToken"); if (token) { config.headers['Authorization'] = 'Bearer ' + token; } } return config; }, error => { Promise.reject(error) }); //Add a response interceptor if(window.location.pathname!=="/user/login"){ axios.interceptors.response.use((response) => { return response }, function (error) { if(error.response.status===404||error.response.status===500||error.response.status===409)return Promise.reject(error); console.log(error.response); if(error.response.status===403){ if(window.sessionStorage.getItem("jwtToken")!==null) message.warning("토큰이 만료되어 로그아웃 됩니다"); window.sessionStorage.removeItem("jwtToken"); this.props.history.push('/user/login'); return Promise.reject(error); } }); }
axios.interceptors.request.use 를 이용해서 jw 토큰 넣어줬음
Q) 이 인터셉터 request, response 알아보기
2.2 eventListenr
window.addEventListener('resize', this.windowSize); windowSize=e=>{ //화면 확대할때 side bar접히게 if(Math.round(window.devicePixelRatio * 100)>300){ this.setState({ collapsed:true, }) } else if(window.screen.width<=500){ this.setState({ collapsed:true, }) } else{ this.setState({ collapsed:false, }) } }
윈도우 사이즈 resize 될때 window.devicePixelRatio 또는 window.screen.width로 가로길이 잼
2.3. 코드 리뷰 받고싶은부분 ?
if(this.props.location.pathname.match("/web/notice")){ this.setState({ openKeys:['sub4'], defaultKeys:['6'], }) } if(this.props.location.pathname.match("/wefl/user")){ this.setState({ openKeys:['7'], defaultKeys:['7'], }) }
네브바에 색이 칠해지는데 그게 새로고침을하고나면 초기화돼서 그거 지정해주려고 componentdidmount될때 url보고 지정해줬었음
이게 맞는건가!
그리고 원래는 뭐 location.어쩌고 바뀐거 적용했는데
componentDidUpdate(prevProps, prevState) { const location = this.props.history.location; const accessToken=window.sessionStorage.getItem("jwtToken"); if(prevProps!==this.props) { if(location.pathname.match("store")){ this.setState({ openKeys:['1'], defaultKeys:['1'], }) } if(location.pathname==="/user/info"){ this.setState({ openKeys:['sub5'], defaultKeys:['8'], })} }}
componentDidupdate로 prevProps와 지금의 상태를 비교해서 다를때만 바꿔줄수있었음
Q) react life cycle?
ㅇㅇ
<Switch> <Route exact path="/" component={this.state.isExpired?Logout:Main}/> <Route exact path={["/store/list/","/store/list/:page","/store/insert","/store/update/:sid"]} component={this.state.isExpired?Logout:ManageStore} /> <Route exact path={["/store/detail/:sid","/store/payment/:sid" ,"/store/data/:sid","/store/webpage/:sid" ,"/store/log/:sid"]} component={this.state.isExpired?Logout:StoreDetail} /> <Route exact path={["/web/notice","/web/notice/insert","/web/notice/update/:id","/web/notice/detail/:id"]} component={this.state.isExpired?Logout:WebsiteManage} /> <Route exact path={["/wefl/user"]} component={this.state.isExpired?Logout:WeflUser}/> <Route exact path={["/user","/user/info","/user/list"]} component={this.state.isExpired?Logout:Admin}/> <Route exact path={["/check/wait/:page","/check/new/:page","/check/return/:page"]}component={this.state.isExpired?Logout:Check}/> <Route exact path={["/check/detail/:status/:sid","/check/webpage/:status/:sid","/check/log/:status/:sid"]} component={this.state.isExpired?Logout:Detail}/> <Route exact path={["/store/error","/check/error"]} component={this.state.isExpired?Logout:StoreError}/> <Route component={this.state.isExpired?Logout:NotFound}/> </Switch>
2.4
breadcrumb
const pathSnippets = window.location.pathname.split("/").filter(i => i); const extraBreadcrumbItems = pathSnippets.map((_, index) => { const url = `/${pathSnippets.slice(0, index + 1).join("/")}`; return ( <Breadcrumb.Item key={url}> {breadcrumbNameMap[url]} </Breadcrumb.Item> ); }); const breadcrumbItems = [ <Breadcrumb.Item key="main"> <Link to="/">위플</Link> </Breadcrumb.Item> ].concat(extraBreadcrumbItems);
2.5
페이징 처리
totalsize, pagecount,
검색하고 삭제하는데 만약에 1페이지가 아닌 상태면 문제생기니깐 다 관리해줬음
다음매장잉 없으면 이전매장을 얻어온다음 그 이전매장의 페이지번호
if(res.data%this.state.pageSize===0) page = res.data/this.state.pageSize;
else page=Math.floor(res.data/this.state.pageSize)+1;
얻어오고 다음매장이 있으면 다음매장의 페이지번호얻어왔음
this.unlisten = this.props.history.listen((location, action) => {
원래 didupate하기전엔 이랬음
Q)queryString.parse location의 search랑 hash 차이
2.6. insert
처음엔 insertStore component불러와서 매장 정보 입력받고 그당므엔 insertWeb불러왔음
뒤로가도 남아있게 , 뒤로간다음 다시 돌아왔을때 남아있게 처리해주느게 어려웠음.
2.7 webpage hash
componentDidUpdate(prevProps,prevState){ if(prevProps!==this.props){ const anchor = this.props.history.location.hash.split('?')[0].split('#')[1]; if(anchor!==undefined&&anchor!==""){ const offset = document.getElementById(anchor).offsetTop; window.scrollTo(0,offset-100); } const query = queryString.parse(this.props.history.location.hash.split('?')[1]); if(query.key!==undefined){ this.setState({ searchKey:query.key, searchValue:query.value, }) } } }
----
예전에 적어둔거 발견해서 붙여넣는다..
- 바벨 : 바벨은 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 코드 자체를 변환시킨다. - create-react-app :페이스북은 쉽게 리액트 프로젝트를 셋업하고 바로 개발에만 집중할 수 있도록 도구를 만들었는데 그게 create-react-app이다. npm install create-react-app으로 설치할 수 있다. (yarn을 쓰는 사람들은 yarn을 써도 된다. yarn은 npm과 같이 자바스크립트 패키지 매니저다. npm이 가진 이슈들을 해결하기 위해 페이스북, 구글 등이 힘을 합쳐 만든 새로운 자바스크립트 패키지 매니저다.) create-react-app을 사용하면 ‘create-react-app my_project’와 같이 순식간이 리액트로 된 페이지를 띄울 수 있는 구조가 만들어진다. - 리액트 초반 필수 설치 라이브러리 react: 리액트를 사용하려면 당연히 리액트 라이브러리가 필요하지 않겠는가? react-dom: 원래는 react에 함께 있었으나 이렇게 따로 떨어져 나왔다. react와 DOM 사이에 연결해주는 역할을 한다. react-scripts: 리액트 프로젝트 초기 셋업을 하는 것은 힘든 일이다. 그걸 보다 쉽고 간편하게 해준다. babel-cli: 바벨을 터미널에서 사용하기 위해 필요하다. 바벨을 왜 쓰는지는 위에서 설명했다. babel-preset-env: 바벨은 babel-preset-es2017과 같이 여러 버전이 있다. 딴거 말고 이거 깔면 알아서 해준다. babel-preset-react: 바벨을 리액트에서 사용하게 해준다 . 우리는 리액트를 쓸거니까 이게 필요하다. 달리 말하면 바벨과 리액트는 별개 프로젝트다. webpack: 웹팩을 쓰기 위해 필요하다. babel-core: 웹팩용 바벨(?)이다. 터미널에서 쓸 때 babel-cli를 썼는데 이걸 웹팩에서 사용하는 용도다. babel-loader: 웹팩에서 바벨을 로드할 때 이 로더를 쓴다. @ cors 오류 - import react 파일에서 JSX 를 사용하려면, 꼭 React 를 import 해주어야 합니다. ( import 를 하는 것은, 우리가 webpack 을 사용하기에 가능한 작업입니다. ) --- index.js에 ReactDOM.render(<App />, document.getElementById('root')); DOM id가 root인애를 public/index.html에서 찾아서 거기에다가 App을 그리도록 하는거 ``` import React ,{Component} from 'react'; class App extends Component { render(){ //클래스 형태의 컴포넌트에는 꼭 render함수가 있어야함 return ( //그 내부에서는 jsx리턴 <div> hello my name is kangjisu </div> ); } } export default App; //우리가 작성한 컴포넌트를 다른 곳에서 불러와 사용할 수 있도록 내보내기 ``` -두개이상의 엘리먼트는 무조건 하나의 엘리먼트로 감싸져있어야함. =>이때 Fragment 사용 (import {Fragment} from 'react'해주어야함) ``` import React, { Component } from 'react'; class App extends Component { render() { const name = 'react'; return ( <div> hello {name}! </div> ); } } export default App; ``` 값을 바꿔줘야할땐 let, 고정되면 const ``` import React, { Component } from 'react'; class App extends Component { render() { const value = 1; return ( <div> { (() => { if (value === 1) return (<div>하나</div>); if (value === 2) return (<div>둘</div>); if (value === 3) return (<div>셋</div>); })() // 화살표함수. this,arguments,supe개념이 없는 익명함수 } </div> ); } } export default App; ``` {/* */} 주석은이렇게 # 4편 :: props 와 state props 는 부모 컴포넌트가 자식 컴포넌트에게 주는 값. 자식컴포넌트에서는 props를 받아오기만 하고 수정할 수 없음 state 는 컴포넌트 내부에서 선언하며 내부에서 값 변경 가능 #5편 componentDidMount() { // 외부 라이브러리 연동: D3, masonry, etc // 컴포넌트에서 필요한 데이터 요청: Ajax, GraphQL, etc // DOM 에 관련된 작업: 스크롤 설정, 크기 읽어오기 등 } 컴포넌트가 화면에 나타나게 됐을때 호출 , 필요데이터 요청위해 axios,fetch등을 통하여 ajax요청이나 돔 속성 읽거나 변경하는 작업 진행 #7편 배열다루기 리액트애서는 state 내부의 값을 직접적으로 수정하면 절대로 안됩니다. 이를 불변성 유지라고 하는데요, push, splice, unshift, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 적합하지 않습니다. 그 대신에, 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용해야합니다. 용어 -파싱 0렌더링 --- 공부순서 팁탭토->https://velopert.com/3480->https://velopert.com/3486 --- AWS, ec2 , nginx 공부 (날개의 노트 사이트 https://wingsnote.com/ 참고) - EC2 : 가상의 컴퓨터(ex:서버) 만들고 관리하는 서비스 - 인스턴스 : EC2에서 만드는 가상의 컴퓨터 하나 ( 실제 컴퓨터의 OS가 아닌 EC2에서 지원해주는 OS사용) - 인스턴스 타입 : 사양을 의미 - AMI : 미리 만들어둔 아마존 가상 머신의 이미지 - AWS는 EC2인스턴스를 만들때 완전 빈 가상 컴퓨터가 아닌 최소한 이미 만들어진 OS가 설치돼있는 이미지 설치 MyAMIs : 유저가 만든거 - 가상화 타입 (HVM vs Paravirtualization) - HVM : 안정성 HIGH 성능 LOW Paravirtualization : 안정성 LOW 성능 HIGH // 두개 비교해서 상대적으로 보면 이렇다는느낌~ - 인스턴스 스토리지 : cdrive느낌 (휘발성이므로 ami,스냅샷 만들어줘야 안날라감) - EBS : 외장 HDD느낌 .지워지면 안되는 데이터들은 이거로 보통. (micro는 ebs) - EC2인스턴스는 보안을 위해 id/pw가 아닌 key 파일을 이용해 접속한다. -> ---.pem파일 (노출안되게 조심!!) - SSH: secure shell protocol :컴퓨터가 public network를 통해 통신할 때 보안상 안전하게 해주는 protocol - NGINX : 경량 웹서버 (아파치같은거.. 아파치는 프로세스와 쓰레드 기반, NGINX는 비동기이벤트방식으로 요청 처리 ) : 모바일 서비스 쪽에 많이 쓰임 - EC2 인스턴스 보안 그룹 설정 : 기본 SSH접근은 22. 웹 브라우저 가능하려면 HTTP 포트 80 설정 해주어야함
'기타 > FE' 카테고리의 다른 글
[React] 서머코딩 3주차 Context/Hook/mock-server (0) 2020.07.20