[ToyProject-Todomate] ํˆฌ๋‘๋ฉ”์ดํŠธ ํด๋ก  ํ”„๋กœ์ ํŠธ 31

2022. 1. 24. 22:19ใ†WEB Dev/ToyProject

728x90


๐Ÿ”ท CloneTodo โ˜‘ - Todomate Clone Project  |  Team CloneMate

 

CloneTodo : ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ๋ž‘ํ•˜๋Š” ํˆฌ๋‘๋ฉ”์ดํŠธ๋ฅผ ํด๋ก ํ•˜์—ฌ ์›น ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•ด๋ณด๋Š” ํ”„๋กœ์ ํŠธ

 


 

 

๋ฒŒ์จ 31๋ฒˆ์งธ ๊ธ€์ด๋‹ค.

 

๊ทธ๋™์•ˆ ํ…€์ด ์ข€ ์žˆ์—ˆ๋Š”๋ฐ ํšŒ์˜๋ฅผ ํ†ตํ•ด ๋ฐฑ์—”๋“œ ํŒ€์›๋ถ„๋“ค๊ณผ ์†Œํ†ตํ•˜๊ณ  ์žˆ์—ˆ๊ณ , MUI์˜ ์บ˜๋ฆฐ๋” ์ปดํฌ๋„ŒํŠธ์ธ DatePicker๋ฅผ ๊ฐ€์ง€๊ณ  ํˆฌ๋‘๋ฉ”์ดํŠธ์˜ ์บ˜๋ฆฐ๋”์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•˜๋Š” ์‹œ๊ฐ„์ด ๊ฝค๋‚˜ ์†Œ์š”๋˜์—ˆ๋‹ค.

์บ˜๋ฆฐ๋” ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์ด ์ฝ”๋“œ๋ฅผ ๊ฑฐ์˜ ๋Œ€๋ถ€๋ถ„ ์ฐธ์กฐํ–ˆ๋‹ค. renderDay ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ ๋‚ ์งœ์˜ ํ•œ ์นธ ํ•œ ์นธ์„ ์ƒˆ๋กœ ๋ Œ๋”๋ง ํ•ด ์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

ํด๋ž˜์Šค๋ฅผ ๋ถ™์—ฌ ์Šคํƒ€์ผ์„ ์ฃผ๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€๋ถ€๋ถ„ ํ•ด๊ฒฐํ–ˆ๋‹ค.

 

 

Customize Material-UI Datepicker With React | Fcode Labs

Material-UI Datepicker is a great Tool we can use as a calendar, but it is a bit confusing to work with and a bit confusing to customize so I decided to share a few things I found about it in this art

www.fcodelabs.com

 

 

์บ˜๋ฆฐ๋”๋ฅผ ๋งŒ๋“ค๋ฉด์„œ ๋ฐฑ์—”๋“œ์™€ ์ฃผ๊ณ  ๋ฐ›๋Š” ๋ถ€๋ถ„์„ ์ƒ๊ฐํ•ด ๋ณผ ๊ธฐํšŒ๊ฐ€ ๋˜์—ˆ๋‹ค. 

์š”์ฒญํ•˜์‹  ๋Œ€๋กœ '๋ฐ์ดํ„ฐ ์–‘์‹' ์ด ์–ด๋–ป๊ฒŒ ๋  ์ง€ ๊ณ ๋ฏผํ•ด๋ณด์•˜๊ณ  ํšŒ์‚ฌ์—์„œ JSON ๋ฐฉ์‹์œผ๋กœ ํ†ต์‹ ํ•˜๋ฉด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„๋‹ค ์“ด ๊ฒฝํ—˜์„ ํ† ๋Œ€๋กœ ๋ฐ์ดํ„ฐ ์–‘์‹์„ ๋งŒ๋“ค์—ˆ๋‹ค.

 

 

 

1. DatePicker๋กœ ์บ˜๋ฆฐ๋” ๊ตฌํ˜„ํ•˜๊ธฐ 

 

 

renderDay props๋กœ ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•จ
day: Date, selectedDate : Date, isInCrrentMonth: boolean, dayComponent: Element
์ด props๋ฅผ ์ž…๋ ฅํ•œ ๋‹ค์Œ ๋‚ ์งœ ํƒ€์ผ๋กœ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

DatePicker๋Š” ์ด ํ•จ์ˆ˜๋ฅผ ํ‘œ์‹œ๋œ ๋ชจ๋“  ๋‚ ์งœ๋กœ ํ˜ธ์ถœ

ํ•„์š”ํ•œ ์ •๋ณด 

- ํˆฌ๋‘๊ฐ€ ์—†๋Š” ๋‚  : normal date tile
- ํˆฌ๋‘๊ฐ€ ์žˆ๋Š” ๋‚  : todo date tile (๊ฐฏ์ˆ˜)
- ํˆฌ๋‘๋ฅผ ๋ชจ๋‘ ์™„๋ฃŒํ•œ ๋‚  : complete date tile(์ƒ‰์ƒ, check โœ”)

๋งŒ๋“  ํ•จ์ˆ˜๋ฅผ enderDate ์š”์†Œ์— ์ง€์ •
๊ทธ๋Ÿฌ๋ฉด DatePicker๊ฐ€ ๋‚ ์งœ๋ฅผ ๋ Œ๋”๋ง ํ•˜๊ณ  ๋‚ ์งœ ํƒ€์ผ์„ ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœํ•ด์ค€๋‹ค.

๋งŒ๋“  ํ•จ์ˆ˜๊ฐ€ ๋‚ ์งœ๋ฅผ ํ™•์ธํ•˜๊ณ  ์ ์ ˆํ•œ ๋‚ ์งœ ํƒ€์ผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋Š”

- ํˆฌ๋‘๊ฐ€ ์žˆ๋Š” ๋‚  theDayhasTodo
- ํˆฌ๋‘๊ฐ€ ์žˆ๋Š” ๋‚ ์˜ ํˆฌ๋‘ ๊ฐฏ์ˆ˜ todoNum
- ํˆฌ๋‘๊ฐ€ ์žˆ๋Š” ๋‚ ์˜ ํˆฌ๋‘ ์™„๋ฃŒ ์ •๋ณด (ํ•ด๋‹น ๋‚ ์งœ์˜ checked ์˜ ๊ฐ’์ด ๋ชจ๋‘ y์ธ๊ฐ€?) todoChecked


if ํˆฌ๋‘ ์žˆ์œผ๋ฉด -> dateTile์— ํˆฌ๋‘๊ฐ€ ์žˆ๋Š” ๋‚ ์˜ ํˆฌ๋‘ ๊ฐฏ์ˆ˜ ๋„ฃ์Œ
   if ํˆฌ๋‘๊ฐ€ ๋ชจ๋‘ ์™„๋ฃŒ ๋˜๋ฉด -> ํˆฌ๋‘ ๊ฐฏ์ˆ˜๊ฐ€ v ํ‘œ์‹œ๋กœ ๋ณ€ํ™˜๋จ

 

 

์ƒ๊ฐ์˜ ๊ตฌ์กฐ๋Š” ์œ„์™€ ๊ฐ™์•˜๋‹ค.

์—ฌ๋Ÿฌ๋ฒˆ ์ฝ”๋“œ๋ฅผ ๊ณ ์ณ์จ๊ฐ€๋ฉด์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ๋•Œ์™€ ์žˆ์„ ๋•Œ ์ˆซ์ž๋ฅผ ๋ฟŒ๋ ค์ฃผ๋Š” ๊ฒƒ, ์™„๋ฃŒ๋˜์—ˆ์„ ๋•Œ ์ˆซ์ž ๋Œ€์‹  ์ฒดํฌํ‘œ์‹œ๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ ๋ชจ๋‘ renderDay ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํด๋ž˜์Šค๋ฅผ ๋ถ™์ด๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ์ฒด์˜ key์™€ value๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

 

 

์œ„์˜ ์ƒ๊ฐ ๊ตฌ์กฐ๋ฅผ ํ† ๋Œ€๋กœ ๋งŒ๋“  ๋ฐ์ดํ„ฐ ์–‘์‹์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

 

//ajax ํ†ต์‹ ์„ ํ†ตํ•ด ๋ฐ›์•„์˜จ ๊ฐ’ (theDayhasTodo, todoNum, todoChecked)
const getTodoDataForCalendar = [ 
	{ theDayhasTodo: '2022-01-08', todoNum: 2, todoChecked: 'n' }, 
        { theDayhasTodo: '2022-01-14', todoNum: 4, todoChecked: 'n', }, 
        { theDayhasTodo: '2022-01-27', todoNum: 6, todoChecked: 'y' } 
];

 

 

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— theDayhasTodo๊ฐ€ YYYY-MM-DD ํ˜•ํƒœ๋กœ ์ €์žฅ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋Œ€๋กœ ๊ฐ’์„ ๋ฐ›์•„์˜ค๋ฉด 

renderDay ํ•จ์ˆ˜๋Š” ๋‚ ์งœ ์ค‘ DD๋ถ€๋ถ„๋งŒ ์ธ์‹ํ•˜๊ณ  01, 02, 03 ์ฒ˜๋Ÿผ ์•ž์— 0๋„ ๋น ์ ธ์•ผํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ๋ถ€๋ถ„์— todoNum ๊ณผ todoChecked๊ฐ€ ๊ฐ๊ฐ ์ž…๋ ฅ๋˜์–ด์•ผ ํ•ด์„œ 

๊ฒฐ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ํ˜•ํƒœ๋Š” { 8: '2', 14: '4', 27: 'y' }์™€ ๊ฐ™๊ฒŒ ๋ณ€ํ™˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

 

 

์ง€๊ธˆ๋ถ€ํ„ฐ ํ•ด์•ผํ•  ๊ฒƒ์€ ๋“œ๋””์–ด recoil์„ ์ ์šฉํ•ด์„œ ๋ณ€์ˆ˜ getTodoDataForCalendar์˜ ๊ฐ’์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋„๋ก ์ƒํƒœ๊ด€๋ฆฌ์™€ ํ†ต์‹  ๋ชจ๋“ˆ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

 

 

 

 

 

 

 

2. Recoil ์ ์šฉํ•˜๊ธฐ

 

 

Recoil ๊ณต์‹ ์ž์Šต์„œ๋Š” ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋œ๋‹ค.

์šฐ์„  ๊ณต์‹ ์ž์Šต์„œ์˜ ์‹œ์ž‘ํ•˜๊ธฐ๋ฅผ ์ฐธ์กฐํ•ด Recoil์˜ atom์„ ์ ์šฉํ•ด๋ณธ๋‹ค.

 

 

Recoil ์‹œ์ž‘ํ•˜๊ธฐ | Recoil

React ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑํ•˜๊ธฐ

recoiljs.org

 

 

 

 

์„ค์น˜

 

 

์•„๋ž˜์™€ ๊ฐ™์ด npm ํ˜น์€ yarn์„ ์ด์šฉํ•œ๋‹ค.

 

 

// npm
npm install recoil
// yarn
yarn add recoil

 

 

 

<RecoilRoot> ๋กœ ๊ฐ์‹ธ๊ธฐ

 

 

Recoil์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” <RecoilRoot> ์ปดํฌ๋„ŒํŠธ๋กœ recoil์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฐ์‹ธ์ค˜์•ผ ํ•œ๋‹ค.

๊ธฐ์กด state๋ฅผ ์ด์šฉํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ๊ฐ€์žฅ ์ƒ์œ„์ธ App ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

index.js์— ๊ฐ€์„œ RecoilRoot๋กœ ๊ฐ์‹ธ์ฃผ์ž.

 

 

 

import React from 'react';
import ReactDOM from 'react-dom';
import './stylesheets/index.css';
import App from './components/App';
import { BrowserRouter } from 'react-router-dom';
import { RecoilRoot } from "recoil";

ReactDOM.render(
  <RecoilRoot>
  <BrowserRouter>
    <App />
  </BrowserRouter>
  </RecoilRoot>,

  document.getElementById('root')
);

 

 

 

 

Atom ๋งŒ๋“ค๊ธฐ

 

 

recoil์—์„œ states๋Š” 'atom' ์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

๊ทธ๋ž˜์„œ atom์˜ ๊ฐ’์— ๋ณ€ํ™”๊ฐ€ ์žˆ์œผ๋ฉด atom์„ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์žฌ๋ Œ๋”๋ง ๋œ๋‹ค.

 

atom์€ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์„ ์–ธ๋œ๋‹ค.

๋ณ„๋„๋กœ ๋งŒ๋“  ํด๋”์— ์„ ์–ธํ•œ atom์ด๊ธฐ ๋•Œ๋ฌธ์— recoil ์—์„œ atom์„ import ํ•ด์ฃผ๊ณ 

atom์œผ๋กœ ๋งŒ๋“  textState๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด export ํ•ด์ค€๋‹ค.

 

import { atom } from "recoil";

export const textState = atom({
  key: 'textState', // unique ID (with respect to other atoms/selectors)
  default: '', // default value (aka initial value)
});

 

 

 

 

useRecoilState Hook

 

 

 

์ด textState๋ผ๋Š” atom์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด atom ์„ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ์— ์•„๋ž˜์™€ ๊ฐ™์€ useRecoilState ํ›…์„ ์‚ฌ์šฉํ•œ๋‹ค.

 

 

const [text, setText] = useRecoilState(textState);

 

 

 

์œ„์˜ ์ˆœ์„œ๋Œ€๋กœ recoil์„ ์ ์šฉํ•ด๋ณด์ž๋ฉด

 

Recoil์„ ์„ค์น˜ํ•œ ํ›„ atom์œผ๋กœ ๋งŒ๋“  state๋“ค์„ ๋ชจ์•„๋‘˜ atoms ์ด๋ผ๋Š” ํด๋”๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ์•ˆ์— todoData๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ ๋‹ค.

 

 

๋‚ด๋ถ€์˜ ์ฝ”๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋„ฃ์–ด์ค€๋‹ค.

 

  const textState = atom({
    key: 'textState', // unique ID (with respect to other atoms/selectors)
    default: '', // default value (aka initial value)
  });

 

 

 

์œ„์˜ textState๋ฅผ ๊ฐ€์ง€๊ณ  atom์„ ์ ์šฉํ•  CalendarBox ์ปดํฌ๋„ŒํŠธ์— ์ด๋Ÿฐ ํ…Œ์ŠคํŠธ ํƒœ๊ทธ๋ฅผ ๋„ฃ์–ด์ค€๋‹ค.

 

 

function TextInput() {
  const [text, setText] = useRecoilState(textState);

  const onChange = (event) => {
    setText(event.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={onChange} />
      <br />
     {text}
    </div>
  );
}

 

 

๊ทธ๋ฆฌ๊ณ  ๋ฆฌ์•กํŠธ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ๋œฌ๋‹ค.

'useRecoilState' is not defined  no-undef

'useRecoilState' is not defined  no-undef

 

 

 

 

ํ•ด๋‹น ์˜ค๋ฅ˜๋Š” ์ƒ๋‹จ์— useRecoilState๊ณผ atom์ด ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ์–ด์คŒ์œผ๋กœ์จ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

import { useRecoilState } from "recoil";
import { textState } from "../atoms/todoData";

 

 

 

์‹คํ–‰

 

 

ํ•ด๋‹น input ํƒœ๊ทธ์— ๊ธ€์ž๋ฅผ ์ž…๋ ฅํ•˜๋ฉด state๊ฐ€ ๋ณ€ํ•˜๋ฉด์„œ ๊ธ€์ž๋ฅผ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

๊ทธ๋Ÿผ ์ด์ œ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜ค๋Š” fetch, promise, axios ๊ฐ™์€ ๋น„๋™๊ธฐ ํ†ต์‹  ๋ฉ”์†Œ๋“œ๋กœ

๋น„๋™๊ธฐ ํ†ต์‹ ์„ ๋‹ด๋‹นํ•˜๋Š” ๋ชจ๋“ˆ์„ ๋งŒ๋“ค์–ด ๋ณด์ž!

 

 

 

728x90