Jieunny의 블로그

React (코딩애플) 본문

React/etc

React (코딩애플)

Jieunny 2021. 12. 27. 22:01
  • 데이터 바인딩 : { 변수명, 함수 등 } ( getElementById 쓸 필요 x )
  • src, id, href 등의 속성에도 사용 가능
  • JSX에서 style 집어넣을 때
    • style={ object 자료형으로 만든 스타일 }
    • 속성명은 camelCase로 작성
    • style={ { color : 'blue' , fontSize : '30px' } 

 

  • component
    • 앱을 이루는 최소한의 단위
    • props나 state 같은 데이터를 입력받아 DOM 노드를 생성한다.
    • 두가지 인스턴스 속성으로 props 나 state 를 갖고있다.
    • 컴포넌트에는 onClick 쓰지 말아라.

 

  • state 
    • 변수 대신 쓰는 데이터 저장 공간
    • useState()를 이용해 만들어야 함.
    • 문자, 숫자, array, object 등 다 저장가능
    • state는 변경되면 HTML이 재렌더링 된다. (새로고침 없이)
    • 자주 바뀌는 중요한 데이터를 state 로 만들어서 써라
    • state는 직접 바꾸는게 아니라 useState 두번째 argument인 함수를 이용해라.

 

  • Deep copy
    • state 변경할 때, 원래 데이터를 새로운 변수에 복사하고 그 복사한 데이터를 변경시켜라.
      • 1) 일단 기존 state 카피본 만들고
      • 2) 카피본에 수정사항 반영하고
      • 3) 변경함수()에 집어넣기 
    • 값공유 x
    • 서로 독립적인 값을 가지는 복사
    • [...data]

 

  • HTML을 한 단어로 줄여서 쓸 수 있는 방법
    • Component
    • 함수 만들고 이름짓고 -> 축약 원하는 HTML 넣고 -> 원하는 곳에서 <함수명 />
    • 이름은 첫문자 대문자
    • return 안에 있는 건 태그 하나로 묶어야 함.
    • 의미 없는 div 쓰기 싫으면 <> </>
    • 어떤 걸 Component 로 만들어야 할까? 
      • 반복적으로 출현하는 HTML 덩어리들
      • 자주 변경되는 HTML UI들
      • 다른 page 만들 때
      • 단점 : state 쓸 때 복잡해짐 ( 상위 컴포넌트에서 만든 state 쓰려면 props 문법 이용해야 함 )

 

  • if문
    • 삼항연산자
    • UI 만드는 법
      • 1) UI 상태를 state로 저장한다. (보통 true / false로 함)
      • 2) state가 true일 때만 UI를 보이게 하게끔 삼항연산자 사용한다.
      • 3) 열기버튼을 누르면 state 상태가 false -> true로 바뀌도록 설정한다.
      • *!prev 사용 하면 열었다 닫았다 가능
      • state는 UI의 현재상태를 보관하는 저장소역할

 

  • for문(반복분)
    • map() 함수 사용
    • array 안의 모든 자료에 똑같은 작업을 하나씩 시켜주고 싶을 때
    • 고유한 값을 key={ 고유한 값 } 으로 주어야 한다.
    • var array = [2,3,4];
      var newArray = array.map(function(a){	// a라는 파라미터는 array안의 데이터들 각각을 뜻한다
        return a * 10
      });
    • 일반 for문 사용
      • function forUI(){
            var array = [];
            for (var i = 0; i < 3; i++) {
              array.push(<div>안녕</div>)
            }
            return array
          }
          return (
            <div>
              HTML 잔뜩있는 곳
              
              { forUI() }
            </div>
          )
  • props : props 는 object일 뿐이고 우리는 그걸 열어서 item을 꺼내 쓰는 것
    • 자식의 부모의 state 가져다 쓰고 싶을 때
    • 1) <자식컴포넌트 전송할이름={state명}> 사용
    • 2) 자식컴포넌트 선언하는 function 안에 파라미터를 하나 만들어준다.

 

  • 사용자가 입력한 데이터를 state로 저장하는 법
    • function App (){
      
        let [input, setInput] = useState('');		// 초깃값 ''
      
        return (
          <div>
            HTML 잔뜩있는 곳...
            <input onChange={ (e)=>{ setInput(e.target.value) } />
          </div>
        )
      }
  • 글 발행 기능 만들기
    • ititle array를 복사해서 copyArray를 만든다. (deep copy)
    • copyArray에 unshift() 를 써서 배열 맨 앞에 자료를 하나 추가한다.
    • setTitle(copyArray) 를 사용해서 title 을 바꿔준다.

 

  • bootstrap 
    • HTML/CSS 쌩코딩하기 싫을때

 

  • 파일 쪼갤 때 활용하는 import / export
    • export : 특정한 파일을 다른 파일에서 쓸 수 있게 한다.
    • 내보내기 : export default 변수명 ( 퉤 뱉고있음 )
    • 가져오기 : import 변수명 from 경로

 

  • 내보낼 변수가 많다면?
    • export { 변수1, 변수2 }

 

  • Route( Hash vs Browser ) : 페이지를 나누자 (뒤로 가기, 앞으로 가기 가능)
    • Hash 
      • 사이트 주소 뒤에 #이 붙는데 # 뒤에 적는 것은 서버로 전달 되지 않아서 리액트가 알아서 잘 라우팅 할 수 있음.
    • Browser 
      •  라우팅을 리액트가 아니라 서버에 요청할 수도 있어서 위험
    • 라우팅 하는 법
      • 1) <Route path="경로"></Route>
      • 2) <Route> 안에 HTML 적기
    • 다른 방법
      • <Route path="/" component={ Modal } />
    • <Route path="/">
        <div>메인페이지에요</div>	
      </Route>
      <Route path="/detail">
        <div>디테일페이지에요</div>
      </Route>	
      
      // 매칭이 되는 것들은 다 보여줌 : "/detail" 페이지에서는 두 div 모두 나타난다.
      // 그럴 땐 <Route exact path="/"> 라고 써주면 "/" 에서만 나타난다.
      
      <Route path="/:id"></Rounte>	//	/모든문자 라는 경로를 의미


  • Link : 새로고침 없이도 유저를 다른페이지로 이동시켜준다. 
    • <Link to="경로"></Link>
    • <Nav.Link><Link to="/">Home</Link></Nav.Link>
    • Link  태그 에러 : a태그 안에 a태그 넣은 거 같아요 ( warning )
    • <Nav.Link as={Link} to="/">Home</Nav.Link>
  • 뒤로가기 버튼 만들기 : useHistory
    • let history = useHistory(); 	// 방문 기록을 저장해놓는 object
      
      return(
        <button className="btn btn-danger" onClick={() => {
          history.goBack();	// 뒤로가기 함수
        }}>뒤로가기</button> 
      );
  • Switch : 여러개가 맞아도 한개만 보여주세요.
    • <Switch> </Switch> 로 모든 <Route> 감쌀 수 있다.
    • 맨 위에서 매칭이 된 path 만 매칭해준다.
  • react-router-dom 이 버전6으로 업그레이드 되면서, 더이상 Switch를 지원하지 않게 됬다.
    • Switch->Routes로 바뀌고, component는 element로 바꼈다.
    • import { BrowserRouter as Router, Link, Routes } from 'react-router-dom';
      
      //버전5
      function App(){
        return(
          <Router>
            <Switch>
              <Route path="/">
                <Home />
              </Route>
            </Switch>
          </Router>
        )
      }
      
      
      //버전6
      function App(){
        return(
          <Router>
            <Routes>
              <Route path="/" element={<Home />} />
            </Routes>
          </Router>
        )
      }

 

  • 아무 문자나 받겠다는 URL 작명법
    • 콜론 뒤에 맘대로 작명
    • 여러개 사용 가능

 

  • useParams 
    • let { id } = useParams();
    • /:id 자리에 사용자가 입력한 값
    • shoes.[id].title 
    • localhost:3000/detail/0 -> 여기서 id 값은 0이 됨.

 

  • styled-component 
    • component 가 많아지면 CSS 작성 고민이 많아진다.
    • 컴포넌트에 CSS 를 직접 장착 (CSS in JS)
    • import styled from 'styled-components';
      
      let Box = styled.div`
          padding : 20px;
        `;
        
      return(
        <Box>안녕</Box>
      }	//	css 미리 적용된 div 만들어짐
    • className 작명 필요없다.
    • 색만 다른 제목이 여러개 필요하다면?
      • let Title = styled.h4`
            font-size: 25px;
            color: ${ props => props.color }
          `;
          
          return(
            <Title color={'red'}>제목</Title> 	//	color="red" 도 가능
          );
  • SASS
    • CSS를 다채롭게 작성할 수 있게하는 전처리기
    • 브라우저는 SASS 모름 -> CSS로 변환해주어야 함.
    • 1) 변수 지정 가능
    • 2) @import 파일 경로 : reset.scss 같은 거 
    • 3) nesting : 셀렉터 대신 씀
      • div.container {
          h4 {
            color: blue;
          }
          p {
            color: pink;
          }
        }	// 얘네는 전부 div.container 안에 있는 거구나
    • 4) 다른 색상의 alert UI 가 필요하다면?
      • @extend .myAlert : 복사, 붙여넣기 기능 하는 것 
      • .myAlert2 {
          @extend .myAlert;
          background: yellow;
        }
    • 5) 함수는 @mixin / @include
      • @mixin function(){
          background: #eeeeee;
          padding: 20px;
          border-radius: 5px;
          max-width: 500px;
          width: 100%;
          margin: auto; 
        }
        
        .myAlert {
          @include function()
        }

 

  • 컴포넌트의 Lifecycle : Hook 으로 인생 중간중간에 명령을 줄 수 있다.
    • useEffect : 컴포넌트가 mount 되었을 때(컴포넌트 등장) or 컴포넌트가 update 되었을 때 특정 코드를 실행할 수 있다.
    • 1) setTimeout(()=>{ 실행할 코드, x }) : x초 후에 코드 실행
      • 주의점 : 타이머 해제 스킬 ( clearTimeout() )
    • 2) 컴포넌트가 사라질 때 코드를 실행시킬 수도 있다.
    • 3) 여러개를 사용하고 싶다면 useEffect() 여러개 사용 가능 : 적은 순서대로 실행된다.
    • useEffect(()=>{
          let timer = setTimeout(()=>{ setShow(false) } , 2000);
          return function a(){	// or return ()=>{} : unmount될때 실행됨 
            clearTimeout(timer)	// 타이머 해제 스킬
          }
        })


    • 4) 특정 state 가 변경될 때만 실행해주세요.
    • let [show, setShow] = useState(true);
        useEffect(()=>{
          let timer = setTimeout(()=>{ setShow(false) } , 2000);
        }, [show])	// show라는 state가 update(재렌더링)될 때만 실행됨.
        // 빈칸이면 Detail 컴포넌트가 업데이트 되던 말던 실행 안됨 (Detail 등장 시 한번 실행하고 끝남)

 

  • Ajax : 서버에 새로고침없이 요청할 수 있게 도와준다.
    • 서버 : 누군가 페이지 요청을 하면 페이지를 갖다주는 프로그램
    • 요청
      • GET 요청 : 주소창에 URL 때려박는 요청 (특정 페이지 / 자료 읽기)
      • POST 요청 : 서버로 중요 정보 전달 (아이디 / 비밀번호)
    • 방법
      • 1) jQuery 설치해서 $.ajax() 쓰던가 : json 그대로 가져온다.
      • 2) axios 설치해서 axios.get() 쓰던가 : json 파일을 가져오면 알아서 object로 바꿔준다.
      • 3) 쌩자바스크립트 fetch() 쓰던가
    • '더보기'버튼 누르면 
      • 1) axios.get(데이터 요청할 URL)
      • 2) 성공하면 .then(()=>{ 성공하면 실행할 코드 })
      • 3) 실패하면 .catch(()=>{ 실패하면 실행할 코드 })
      • ajax로 가져온 자료 출력하는 방법 : .then((가져온자료) => {}) 
        • axios.get('https://codingapple1.github.io/shop/data2.json')
            .then((result)=>{})
            .catch(()=>{})


        • setShoes([...shoes, ...result.data])
          // shoes 라는 state에 result.data(ajax로 가져온 데이터) 추가
          // ...(spread) 는 '[' 기호 벗긴다.

 

  • 컴포넌트 많은데 props 쓰기 싫을 때 => createContext() : 범위를 생성해주는 문법.
    • let remainContext = React.createContext();	// 같은 변수값을 공유할 범위 생성
    • context 만들기
      • 1) React.createContext() 로 범위 생성
      • 2) 같은 값을 공유할 HTML을 <범위.Provider> 로 감싸고 value={공유 원하는 값}
      • <remainContext.Provider>
        
          <div className="row">
            {
              shoes.map((a, i)=>{
                return <Item key={i} shoes={shoes[i]} i={i} />	
                // 이제 Item 컴포넌트는 props 전송 없이도 remain state 갖다 쓸 수 있음.
              })
            }
          </div>
        
        </remainContext.Provider>
      • 3) useContext(범위이름)로 공유된 값 사용하기
      • 다른 파일에 변수 공유하려면 export 해줘야 한다. 그리고 사용할 파일에서 import 해준다.
        • export let remainContext = React.createContext();  // App.js
          import { remainContext } from './App.js' // Detail.js

 

  • Redux 라이브러리 
    • 모든 컴포넌트 파일들이 같은 값을 공유할 수 있는 저장공간 생성가능
    • state 데이터 관리 가능
    • redux 에선 state 데이터의 수정방법을 미리 정의합니다.
    • redux 같은 라이브러리는 대형 프로젝트에서 유용하게 쓰인다.
    • 쓰는 이유
      • 1) props 없이 모든 컴포넌트가 state를 갖다쓰기 가능
      • 2) state 데이터 관리 기능 ( state 에러 추적 용이 )
    • 사용 방법
      • 1) index.js에 import { Provider } from 'react-redux'
      • 2) <Provider> 로 <App> 감싸기
      • 3) createStore() 안에 state 저장
      • 4) Provider 에 props로 전송
    • 컴포넌트에서 store에 있는 state 쓰려면
      • 1) function 만들기 : redux store 데이터 가져와서 props로 변환해주는 함수( state를 props화 )
      • 2) export default connect()()
      • 더 쉬운 방법 : hook을 이용하면 훨씬 쉬워짐.
        • 둘다 return 위에 선언 
        • useSelector()
        • let state = useSelector((state) => state);
          state.reducer.map((a,i)=> 	// 이런식으로 사용. 이제 props.state 로 쓸 필요 없음
        • useDispatch()
        • <button onClick={()=>{
            dispatch({type : '수량감소'})
          }}>-</button>
    • redux에서 state 수정하기
      • 수정방법을 정의해놓자 : reducer 
      • reducer : 수정된 state를 퉤 뱉는 함수
      • dispatch() 한다.
    • // index.js
      
      let initialState = [
        { id: 0, name: '빨간 신발', quan: 2}, 
            { id: 1, name: '파란 신발', quan: 3},
            { id: 2, name: '노란 신발', quan: 0} 
      ];
      
      function reducer(state = initialState, action){  //  default 파라미터 문법
        if(action.type === '수량증가'){
          let copy = [...state];
          copy[0].quan++;
          return copy;
        }
        else if(action.type === '수량감소'){
          let copy = [...state];
          copy[0].quan--;
          return copy;
        }
        else{
          return state;
        }
      }
      
      let store = createStore(reducer);
    • // Cart.js
      
      <tbody>
              {
                props.state.map((a, i)=>{
                  return (
                    <tr key={i}>
                      <td>{ a.id }</td>
                      <td>{ a.name }</td>
                      <td>{ a.quan }</td>
                      <td><button onClick={()=>{
                        props.dispatch({type : '수량증가'})
                      }}>+</button>
                      <button onClick={()=>{
                        props.dispatch({type : '수량감소'})
                      }}>-</button>
                      </td>
                    </tr>
                  )
                })
              }  
          </tbody>
    • state 여러개 만들기
      • 변수, reducer 또 만들어주기
      • let alertInitial = true;
        
        function reducer2(state = alertInitial, action){
          return state;
        }
      • reducer를 더 만들었으면 combineReducers({ reducer, reducer2 });
        • let store = createStore(combineReducers(reducer, reducer2));
        • reducer 몇개 합치면 store 데이터 뽑아 쓸 때도 주의!!
        • function 함수명(state){
            return {
              state : state.reducer,
              alertOpen : state.reducer2
            }
          }
          export default connect(함수명)(Cart);
    • redux 에 온갖 데이터 저장하지 마라 ( 선택적으로 쓰는 거임 )
    • 한 컴포넌트에서만 쓰는 데이터는 굳이 redux 에 저장할 필요 x

 

 

 

  • Tab UI 만드는 법
    • 1) 몇번째 버튼 눌렀는지를 state로 저장해둠.
    • 2) state에 따라 UI 보이게 / 안보이게
    •  
    • function TabContent({ tab }){ if (tab === 0) { return <div>0번째</div> } else if (tab === 1) { return <div>1번째</div> } else { return <div>2번째</div> } } // 삼항연산자는 조건 줄 수 없으므로 if문 만들고 싶으면 따로 component 하나 만들어서 해라.
    • 애니메이션 추가는?
      • 1) 미리 애니메이션 주는 class 정의 해 놓고
      • 2) 컴포넌트 등장 / 업데이트 될 때마다 className에 부착
      • 귀찮으면 걍 라이브러리 써..
        • 1) import { CSSTransition } from 'react-transition-group'
        • 2) <CSSTransition> 으로 애니메이션 필요한 곳 감싸기
        • 3) in={애니메이션 동작 스위치(true 일 때만 동작)}, classNames="class작명", timeout={애니메이션 얼마나 실행할 지} 넣기
        • 4) class로 애니메이션 넣기
        • // 애니메이션 클래스 이름 wow
          
          .wow-enter {	// 애니메이션 시작할 때 적용할 CSS
            opacity : 0;
          }
          
          .wow-enter-active {		// 애니메이션 동작 때 적용할 CSS
            opacity: 1;
            transition: all 500ms;
          }
        • 5) 원할 때 스위치 켜기 : 스위치는 state 로 만들어 놓고 바꿔라.

 

 

  • 리액트에서 자주 쓰는 if문
    • 1) 컴포넌트 안에서 쓰는 if / else
      • function Component() {
          if (true) {
            return <p>참이면 보여줄 HTML<p>;
          }
          else {	//  else는 생략가능
            return null;
          }
        }
      • 우리가 자주 쓰던 if 문은 return() 안의 JSX에서 사용 불가능하다.
      • <div> if ~~ </div> 불가능하다는 뜻
    • 2) JSX안에서 쓰는 삼항연산자
      • 조건문 ? 참일때 코드 : 거짓일때 코드
      • 그냥 if 와는 다르게 JSX 안에서도 사용 가능하다.
      • function Component() {
          return (
            <div>
              {
                1 === 1
                ? <p>참이면 보여줄 HTML</p>
                : null
              }
            </div>
          )
        }
    • 3) && 연산자로 if 역할 대신하기
      • 자바스크립트에는 && 연산자가 있다
      • 왼쪽 오른쪽 둘다 true면 전체를 true로 바꿔주세요.
        • true && false;	// false가 남음
          true && true;	// true가 남음
      • boolean 이 아닌 자료형을 넣으면 이상한 현상
        • true && '안녕';	// '안녕'
          false && '안녕';	// false
      • 만약에 이 변수가 참이면 <p></p>를 뱉고 아니면 null을 뱉어라.
        • function Component() {
            return (
              <div>
                {
                  1 === 1 && <p>참이면 보여줄 HTML</p>
                }
              </div>
            )
          }
        • 왼쪽 조건식이 true 면 오른쪽 JSX가 그 자리에 남고, 왼쪽 조건식이 false 면 false 가 그 자리에 남는다.
    • 4) switch / case 조건문
      • if 문이 중첩해서 여러개 달려있을 때 쓴다.
      • function reducer(state, 액션){
          
          switch (액션.type) {
            case '수량증가' :
              return 수량증가된state;
            case '수량감소' : 
              return 수량감소된state;
            default : 
              return state
          }
        
        }
    • 5) object 자료형을 응용한 enum
      • 경우에 따라서 다른 HTML을 보여주고 싶은 경우
        • function Component() {
            var 현재상태 = 'info';
            return (
              <div>
                {
                  { 
                     info : <p>상품정보</p>,
                     shipping : <p>배송관련</p>,
                     refund : <p>환불약관</p>
                  }[현재상태]
                }
          
              </div>
            )
          }
        • object 자료형으로 HTML을 다 정리해서 담는다.
        • 마지막 object{} 뒤에 []를 붙여서 "key값이 현재상태인 값을 뽑겠습니다" 라고 써놓는다.
        • 그럼, 현재상태라는 변수의 값에 따라서 원하는 HTML 을 보여줄 수 있다.

 

  • state 변경함수 사용할 때 주의점 : async
    • 자바스크립트 sync / async 관련 상식
      • 자바스크립트는 코드를 적은 순서대로 윗줄부터 차례로 코드가 실행된다 (=synchronous)
      • 이상한 함수들을 실행하면 asynchronous 하게 실행된다. ex) ajax, 이벤트리스너, setTimeout 등
      • 이런 함수들은 처리시간이 오래 걸리기 때문이다.
    • function App(){
        let [name, setName] = useState('kim')
      }
    • 여기서 setName 같은 state 변경 함수들은 전부 asynchronous 으로 처리된다.
    • setName 이 오래걸리면 제껴두고 밑에 있는 다른 코드들부터 실행한다는 뜻이다.
    • <button onClick={()=>{
      
        setCount(count+1);
        if ( count < 3 ) {
          setAge(age+1);
        }
               
      }}>누르면한살먹기</button>
    • 여기서 count 가 3이면 age+1을 해주면 안되는데 해주고 있다.
    • 이유는 state 변경함수가 asynchronous 하게 처리되는 함수이기 때문에 count를 3으로 만드는 게 오래걸리니까 밑에있는 count < 3 부터 실행하는데, 이때 count는 아직 2 이므로 age+1 이 실행된다.
    • 해결책은 useEffect() 임 : useEffect를 사용하면 특정 state가 변경될 때만 코드를 실행할 수 있다.

 

  • 성능 잡기
    • 1) 함수나 오브젝트는 선언해서 써라 : 메모리 할당 문제 때문
    • 2) 애니메이션 막 주지 말고 ( margin, width, padding 이런 레이아웃 변경하는 속성들을 변경하면 시간이 오래걸림 ) 되도록 transform ( ratate, skew, scale, translate ) 사용하자.
    • 3) 컴포넌트 import 할때 lazy loading 하자.
      • lazy loading : 컴포넌트가 필요할 때 import 해주세요.
      • import React, { lazy, Suspense } from 'react';
        let Detail = lazy(()=>{ return import('./Detail.js') }); 
        //	Detail 컴포넌트가 필요해진 순간이 왔을 때 import 해준다.
        //  return 할게 하나밖에 없으면 {} 랑 return 생략가능
        
        
        function App(){
        	return(
              <div>
                <Suspense fallback={<div>로딩중이에요</div>}>	// Suspense 태그로 묶어줘야함
                  <Detail />
               </Suspense>
              </div>
            )
        }
      • fallback : 컴포넌트 로딩하는 동안 임시메세지 

 

  • 쓸데없는 재렌더링을 막는 memo
    • 컴포넌트에 있는 props 나 state 변경되면 그거 쓰는 HTML 전부 재렌더링
    • memo를 사용하면 불필요한 재렌더링 막기 가능 ( props 가 변경이 안된 컴포넌트는 재렌더링 하지 말아주세요 ) 
    • import React, { memo, useEffect } from 'react';
      
      fuction App(props){
      	return(
            <div>
              <Parent 이름="지은" 나이="24" />
            </div>
          )
      }
      
      function Parent(props){
      	return(
            <div>
              <Child1 이름={props.이름}></Child1>
              <Child2 나이={props.나이}></Child2>
            </div>
          )
      }
      
      function Child1(){
        useEffect(()=>{
          console.log('렌더링됨1');
        })
        return <div>1111</div>
      }
      
      let Child2 = memo(function(){	// 함수 만드는 다른 방법, memo로 함수 감싸기
        useEffect(()=>{
          console.log('렌더링됨2');
        })
        return <div>2222</div>
      });
    • 이름="존박" 을 이름="존박1" 으로 변경하면 Child1은 재렌더링 되지만 Child2는 재렌더링 되지 않음.
    • memo의 단점 : 기존 props vs 바뀐 props 비교연산 후 컴포넌트 업데이트 할지말지 결정함.

 

  • PWA: 웹사이트를 모바일 앱처럼 설치해서 쓸 수 있음.
    • 장점 
      • 1) 설치 마케팅 비용 적음
      • 2) 아날로그 유저들 배려
      • 3) html, css, js 만으로 앱까지 만들 수 있음
      • 4) 푸시알림, 센서 등
    • 세팅 방법
      • 1) PWA 가 셋팅된 리액트 프로젝트 생성
        • npx create-react-app 프로젝트명 --template cra-template-pwa
        • pwa의 조건 : manifest.json / service-worker.js 파일 있어야함.
      • 2) index.js 에서 .unregister() 있는 코드 .register() 로 바꾼다.
      • 3) npm run build 하면 service-worker.js 생김 : 오프라인에서도 사이트 열 수 있게 도와줌 ( 사이트 접속할 때 html css js 다운받지 말고 하드에 있던거 써라 )

'React > etc' 카테고리의 다른 글

리액트의 확장자 JSX  (0) 2022.01.01
블로그  (0) 2021.12.28
CSS 속성 선언 순서  (0) 2021.12.26
CRA 없이 React 환경 구축  (0) 2021.12.19
TypeScript  (0) 2021.12.18