리액트 스터디 4

26580 단어 React리액트React

keyframes

keyframesstyled-components에 포함되어 있는 기술로 웹 애니메이션 구현을 돕는다.

import styled, { keyframes } from 'styled-components';

function App() {
  return (
    <div className="App">
      <Box></Box>
    </div>
  );
}

const move = keyframes`
  0%{
    top: 20px;
    opacity: 1;
    left: 20px;
    background: green;
  }
  
  30%{
    top: 50px;
    background: orange;
  }

  50%{
    top: 200px;
    opacity: 0;
    left: 200px;
  }
  
  80%{
    top: 150px;
  }

  100%{
    top: 20px;
    opacity: 1;
    left: 20px;
    background: blue;
  }  
`;

const Box = styled.div`
  width: 300px;
  height: 300px;
  background-color: green;
  border-radius: 150px;
  position: absolute;
  top: 20px;
  left: 20px;
  animation: ${move} 2s 1s infinite;
  opacity: 1;
`;


export default App;

위의 코드와 같이 프레임 단위로 다양한 애니메이션을 직관적으로 작성할 수 있다. 코드를 실행하면 마름모의 궤적을 그리며 색과 투명도가 변하는 원을 볼 수 있다.

Progress Bar

프로그레스바를 구현해보자. 먼저 ducks module에 새로운 action, action creator, reducer case를 만들어 보자.

// action
...
const UPDATE = "bucket/UPDATE";
...

// action ctreator
export const updagteBucket = (bucket) => {
    return { type: UPDATE, bucket };
}
...

// switch in Reducer
...
case "bucket/UPDATE": {
            const bucket_list = state.list.map((l, idx) => {
                if (idx === action.bucket) {
                    return { ...l, completed: true };
                } else {
                    return l;
                }
            })
            return { list: bucket_list };
        }
...

개별 요소의 화면에 해당되는 Detail.js에서 기존의 deleteBucket 옆에 연결해 준 뒤 홈 화면에 해당되는 App.js에서 적당한 위치에 <Progress /> 컴포넌트를 만들어 연결해 준다.

import { useSelector, useDispatch } from 'react-redux'
import { deleteBucket, updagteBucket } from './redux/modules/bucket';
...
<Button onClick={() => {
                    dispatch(updagteBucket(bucket_index));
                    props.history.goBack();
                }}>완료</Button>

마지막으로 Progress.js를 작성하자. completed의 값이 참인 수 만큼 스타일을 채워준다.

import React from 'react'
import styled from 'styled-components'
import { useSelector } from 'react-redux'

export const Progress = () => {
    const bucket_list = useSelector(state => state.bucket.list);
    let count = bucket_list.filter(l => l.completed === true).length;

    return (
        <ProgressBar>
            <HighLight width={(count / bucket_list.length) * 100 + "%"} />
        </ProgressBar>
    )
}

const ProgressBar = styled.div`
    background-color: #eee;
    width: 100%;
    height: 40px;
`;

const HighLight = styled.div`
    background-color: orange;
    height: 40px;
    width: ${props => props.width};
    transition: width 1s;
`;

Scroll Bar

홈 화면인 App.js에서 최하단에 구현한다. scrollTo 는 기본적으로 x, y 좌표인 두개의 인자를 받는데 부드럽게 올라가도록 behavior 옵션을 주기위해 아래 코드처럼 딕셔너리 형태로 작성한다.

<button onClick={() => {
          window.scrollTo({ top: 0, left: 0, behavior: "smooth" });
        }}>top</button>

Firestore

Baas 서비스 중 하나인 FireBaseFirestore를 사용해보자. 구글 계정으로 진행한다.

시작하기를 누르고 적당한 프로젝트명을 정해서 계속을 누른다.

프로젝트가 완료되면 좌측 상단 메뉴에서 빌드Firestore Database를 선택한다.

Firestore DB는 클라우드 NoSQL로 JSON 형태로 데이터를 저장할 수 있어 백엔드에 대한 부담없이 프론테엔드에 집중해 스터디 할 수 있도록 도와준다. 중앙의 데이터 베이스 만들기를 누르면 다음과 같은 설정이 나타난다.

로컬에서의 개발을 빠르게 시작하기 위해 테스트 모드에서 시작을 선택하고 다음을 누른다. 언제든지 프로덕션 모드로 변경할 수 있다. 이제 물리적인 DB에 할당할 곳을 정한다. 이 위치는 실제 지형을 의미하기 때문에 한번 정하면 변경할 수 없다. asia-northeast2를 선택하고 사용 설정을 눌러준다.

완성된 대시보드에서 +컬렉션 시작을 누르고 컬렉션(문서의 집합인데 일단은 RDBMS의 스키마와 비슷한 개념으로 이해하자) 이름을 설정한다.

이어서 문서(테이블 같은 개념)와 필드를 작성한다. 완성된 문서와 내부의 필드는 대시보드를 통한 입력, 수정, 삭제 기능을 지원한다.

이제 리액트에 연동해보자. bash에서 다음의 명령어를 입력한다.

yarn add firebase

srcfirebase.js를 만들고 다음과 같이 설정한다.

import firebase from 'firebase/app';
import "firebase/firestore";

const firebaseConfig = {
}

firebase.initializeApp(firebaseConfig);

const firestore = firebase.firestore();

export { firestore };

작성이 끝나면 다시 대시보드 메인으로 돌아가서 앱에 Firebase 추가하여 시작하기 화면에서 </>(웹)을 선택해 준다.

이후 화면에서 앱의 닉네임을 정해주고 앱 등록을 누른다.

다음 절차에서 fireBaseConfig안의 값들을 복사하여 방금 작성한 firebase.js 파일의 const firebase = {} 안쪽에 복사하여 값을 채워준다.

App.js로 돌아가 firestore를 연결해주면 설정은 끝난다. componentDidMount에서 firebase를 출력해보면 간단하게 연결을 확인할 수 있다.

import { firestore } from "./firebase";
...
componentDidMount() {
  // 컬렉션 가져오기
  const bucket = firestore.collection("bucket");
  
  // 특정 문서(bucket_item1) 가져오기
  bucket.doc("bucket_item1").get().then((doc) => {
      console.log(doc.data());
      console.log(doc.id);
    }); 
  
  // 모든 문서 가져오기
  bucket.get().then(docs => {
      let bucket_data = [];
      docs.forEach((doc) => {
        if (doc.exists) bucket_data = [...bucket_data, { id: doc.id, ...doc.data() }]
      })
      console.log(bucket_data);
    });
}
...

CRUD

이제부터는 입력, 수정, 삭제를 구현해보자. id를 주지 않으면 자동으로 유니크한 아이디가 부여된다. docRef.id을 통해 꺼내볼 수 있다. 또한 없는 컬렉션을 연결하면 해당 이름의 컬렉션이 추가된다.

    // 입력
    bucket.add({ text: "그림 배우기", completed: false }).then((docRef) => {
      console.log(docRef);
      console.log(docRef.id);
    })

    // 수정
    bucket.doc("bucket_item1").update({ text: "리액트 공부" });

    // 삭제
    bucket.doc("bucket_item1").delete();

좋은 웹페이지 즐겨찾기