본문 바로가기
개발 일지/TIL

[ 스파르타 / TIL ] 내일배움캠프 #42

by CODESIGN 2022. 12. 28.

오늘 한 것


  • LOVERDUCK 프로젝트 마무리 및 발표 자료 준비
  • LOVERDUCK 프로젝트 회고 작성

 

 

input값에 maxLength 지정하기


input창에 받는 입력값의 길이를 지정하려고 했지만 잘 되지 않았다.

아래와 같이 길이 제한을 6으로 뒀지만 계속 입력이 되었다.

 

<input type='text' maxlength='6' />

 

위의 코드가 유효하려면 input의 type이 'text, search, url, tel, email, password' 일 경우에만 유효하다.

하지만 type이 'number'일 경우에는 유효하지 않았다.

그래서 아래와 같은 방법으로 사용했다.

 

if (inputCost.length > 7) {
	inputCost = inputCost.substr(0, 7);
}

 

 

Problem


1.  React-Redux에 Firebase 연결 및 useState를 이용한 비동기 처리

 

Firebase에서 데이터를 가져오기 위해서는 아래와 같이 적는다.

 

import { getFirestore, query, collection, getDocs } from "firebase/firestore";
import { dbService } from "../firebase";

const q = query(collection(dbService, "datetoString"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => doc.data());

 

위의 코드를 어떻게 상태로 저장할 수 있을지가 어려웠다.

useState 훅을 이용하여 아래와 같이 코드를 작성해 주었다.

아래의 코드는 쇼핑 아이템들을 볼 수 있는 페이지의 component가 monunt 되기 전에 item을 가져오도록 했다.

 

let [items, setItems] = useState([]);

const fetchItem = ( ) => {
  // 서버에서 items 배열을 가져오는 작업
  const q = query(collection(dbService, "dateToString")); 
  const querySnapshot = await getDocs(q);
  querySnapshot.forEach((doc) => setItems([doc.data(), ...items]));
}

useEffect(()=>{
  fetchItem();
},[])

 

하지만 redux로 상태 관리 중이어서 비동기 처리하기가 어려웠다. 그러던 중 redux-thunk를 알게 되었다.

 

redux-thunk
- 하나의 action에서 여러 개의 다른 action을 호출할 수 있다.
- action이 dispatch 되는 걸 조작할 수 있어, 비동기 처리에도 사용이 가능하다.

 

먼저 아래 두 개를 설치해 주었다.

 

// redux-thunk install
npm install redux-thunk

// redux-thunk-firebase install
npm intall react-redux-firebase

 

 

firebase.js 파일


import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { useState, useEffect } from "react";
import { getAuth } from "firebase/auth";
import { getStorage } from "firebase/storage";
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  onAuthStateChanged,
  signOut,
  updateProfile,
} from "firebase/auth";

const firebaseConfig = {
  ... 
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const db = getFirestore();
export const auth = getAuth();
export const storage = getStorage();

 

redux-thunk setting


Items의 action을 처리해줄 Reducer 파일을 생성해 주었다. 액션은 case 별로 구별해 주고, default(기본 상태)는 state를 리턴해주었다.

 

 

itemsAction.js


상황에 따라 필요한 action을 만들어 준다.

 

//  Action Value
const ADD_LIST = 'ADD_LIST';
const DELETE_LIST = 'DELETE_LIST';

// Firestore에서 collection을 가져옴
const list_db = firestore.collection('shoppingList');

// LIST를 추가하는 Action Creator
export const addList = (shoppingList) => {
  return {
    type: ADD_LIST,
    shoppingList,
  };
};

// LIST를 삭제하는 Action Creator
export const deleteList = (shoppingList) => {
  return {
    type: DELETE_LIST,
    shoppingList,
  };
};


// Action Creator
// LIST를 추가하는 Action Creator
export const addList = (payload) => {
  return {
    type: ADD_LIST,
    payload,
  };
};

// LIST를 삭제하는 Action Creator
export const deleteList = (payload) => {
  return {
    type: DELETE_LIST,
    payload,
  };
};

 

 

ItemReducer.js 


const lists = (state = initialState, action) => {
  switch (action.type) {
    case ADD_LIST:
      return [
        ...state,
        {
          id: action.payload.id,
          name: action.payload.name,
          date: action.payload.date,
          price: action.payload.price,
          isChecked: action.payload.isChecked,
        },
      ];
    case DELETE_LIST:
      return state.filter((item) => {
        return item.id !== action.payload;
      });
    }
    default:
      return state;
  }
};
export default lists;

 

 

rootReducer.js


store에 저장될 rootReducer를 만들어준다. Reducer이 2개 이상일 경우에는 combineReducer로 묶어주면 된다.

 

import { createStore, combineReducers, applyMiddleware } from "redux";
import shoppingList from "../modules/shoppingListActions";
import lists from "../modules/list";
import comments from "../modules/comment";
import profileName from "../modules/profile";
// import ItemsReducer from '../modules/ItemReducer';
const rootReducer = combineReducers({
  lists,
  comments,
  shoppingList,
  profileName,
});

export default rootReducer;

 

store.js


마지막으로 store를 묶어주었다.

 

import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import App from './App';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../src/redux/config/configStore';
import thunk from 'redux-thunk';

const container = document.getElementById('root');
const root = createRoot(container);
const store = createStore(rootReducer, applyMiddleware(thunk));

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

 

 

댓글