Project/Toy-project

๊ฐ์ •์ผ๊ธฐ์žฅ ๋งŒ๋“ค๊ธฐ 1 - ๊ธฐ์ดˆ ์ž‘์—…

Dong _ hwa 2023. 5. 19. 00:25

๊ธฐ์ดˆ ๊ณต์‚ฌ ๐Ÿช›

font

๊ตฌ๊ธ€ ํฐํŠธ๋ณด๋‹ค ๋‚ด๊ฐ€ ์ข‹์•„ํ•˜๋Š” ํฐํŠธ๊ฐ€ ๋งŽ์€ ๋ˆˆ๋ˆ„ ํฐํŠธ ์ด์šฉ.
https://noonnu.cc/

App.css

@font-face {
  font-family: "Humanbumsuk";
  src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2210-2@1.0/Humanbumsuk.woff2")
    format("woff2");
  font-weight: normal;
  font-style: normal;
}

๊ทธ๋ฆฌ๊ณ  App.js ์—์„œimport "./App.css"; ํ•˜๋ฉด ๋!
๊ฐ–๋‹ค ์“ฐ๊ณ  ์‹ถ์€ ๊ณณ์— font-family: "Humanbumsuk"์“ฐ๋ฉด ๋œ๋‹น

 

 

images

๋‚˜์˜ ๊ฐ์ •ํ‘œ์‹œ ์•„์ด์ฝ˜์ด๋‹ค.
๋ณด๋ฆ„๋‹ฌ์ผ์ˆ˜๋ก ๋งค์šฐ ๊ธฐ๋ถ„ ์ข‹์€ ์ƒํƒœ :D !

<img src={process.env.PUBLIC_URL + `/assets/emotion1.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion2.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion3.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion4.png`} />
<img src={process.env.PUBLIC_URL + `/assets/emotion5.png`} />

import ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋„ˆ๋ฌด ๋งŽ๊ณ  ์ƒ๋Œ€๋กœ ์ ๊ธฐ ์‹ซ์–ดํ•˜๋Š” ์‚ฌ๋žŒ (๋‚˜์•ผ๋‚˜) ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—...
์•„๋ฌดํŠผ..

public ์ด๋ผ๋Š” ํด๋” ์•ˆ์— ์ž๋ฃŒ๊ฐ€ ์žˆ๋‹ค๋ฉด,
html ์—์„œ๋Š” %PUBLIC_URL%
js ์—์„œ๋Š” process.env.PUBLIC_URL ์“ฐ๋ฉด ๋จ!

 

 

Button

MyButton.js

const MyButton = ({ text, type, onClick }) => {
  // positive, negative, default ์™ธ์˜ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๋ฒ„ํŠผ ์ƒ์„ฑ์‹œ์—๋Š” default๋กœ
  const btnType = ["positive", "negative"].includes(type) ? type : "default";

  return (
    <button
      className={["MyButton", `MyButton_${btnType}`].join(" ")}
      onClick={onClick}
    >
      {text}
    </button>
  );
};

MyButton.defaultProps = {
  type: "default",
};

export default MyButton;

ํƒ€์ž…๋ช…์ด positive, negative๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ์—๋Š” ๋ชจ๋‘ default๋กœ.

App.js

<MyButton
          text={"BUTTON"}
          onClick={() => alert("๋ฒ„ํŠผ ํด๋ฆญ")}
          type={"positive"}
        />
        <MyButton
          text={"BUTTON"}
          onClick={() => alert("๋ฒ„ํŠผ ํด๋ฆญ")}
          type={"negative"}
        />
        <MyButton
          text={"BUTTON"}
          onClick={() => alert("๋ฒ„ํŠผ ํด๋ฆญ")}
          type={"asdf์•„๋ฌด๊ฑฐ๋‚˜ ์ด๋ฆ„์ง€์–ด"}
        />
        <MyButton text={"BUTTON"} onClick={() => alert("๋ฒ„ํŠผ ํด๋ฆญ")} />

3,4๋ฒˆ์งธ ๋ฒ„ํŠผ์€ type๋ช…์ด "asdf์•„๋ฌด๊ฑฐ๋‚˜ ์ด๋ฆ„์ง€์–ด", ์ด๊ฑฐ๋‚˜ ์•„๋‹ˆ๋ฉด type์ด ์—†๋Š”๋ฐ, ํ™•์ธํ•ด๋ณด๋ฉด default๋กœ ์ž˜ ๋“ค์–ด์™€์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค!

  /* ๋ฒ„ํŠผ ๋‚ด ๊ธ€์ž๊ฐ€ ์งค๋ ค์„œ ๋‘ ์ค„์ด ๋˜์ง€ ์•Š๊ฒŒ ํ•จ */
  white-space: nowrap;




๊ณตํ†ต components

Header, Button์„ ๋งŒ๋“ค์–ด ๋ณธ๋‹ค.

MyHeader.js

const MyHeader = ({ headtext, leftchild, rightchild }) => {
  return (
    <header>
      <div className="head_btn_left">{leftchild}</div>
      <div className="head_text">{headtext}</div>
      <div className="head_btn_right">{rightchild}</div>
    </header>
  );
};

export default MyHeader;

App.js

        <MyHeader
          headtext={"App"}
          leftchild={
            <MyButton text={"LEFT"} onClick={() => alert("์™ผ์ชฝ ํด๋ฆญ")} />
          }
          rightchild={
            <MyButton text={"RIGHT"} onClick={() => alert("์˜ค๋ฅธ์ชฝ ํด๋ฆญ")} />
          }
        />









๊ธฐ๋ณธ ๊ณต์‚ฌ ๐Ÿ‘ท๐Ÿป‍โ™‚๏ธ

์ƒํƒœ ๊ด€๋ฆฌ ๋กœ์ง

์ „๋ฐ˜์ ์œผ๋กœ ์“ฐ๊ฒŒ ๋  ์ƒํƒœ๊ด€๋ฆฌ ๋กœ์ง ๊ตฌํ˜„
useReducer๋ฅผ ์ด์šฉํ•œ๋‹ค.

App.js

import React, { useReducer, useRef } from "react";
..

const reducer = (state, action) => {
  let newState = [];
  switch (action.type) {
    case "INIT": {
      return action.data;
    }
    case "CREATE": {
      // const newItem = {
      //   ...action.data,
      // };
      // newState = [newItem, ...state];
      newState = [action.data, ...state];
      break;
    }
    case "REMOVE": {
      newState = state.filter((it) => it.id !== action.targetId);
      break;
    }
    case "EDIT": {
      newState = state.map((it) =>
        it.id === action.data.id ? { ...action.data } : it
      );
    }
    // eslint-disable-next-line no-fallthrough
    default:
      return state;
  }
  return newState;
};

function App() {
  const [data, dispatch] = useReducer(reducer, []);

  const dataId = useRef(0);

  // CREATE
  const onCreate = (date, content, emotion) => {
    dispatch({
      type: "CREATE",
      data: {
        id: dataId.current,
        date: new Date(date).getTime(),
        content,
        emotion,
      },
    });
    dataId.current++;
  };

  // REMOVE
  const onRemove = (targetId) => {
    dispatch({ type: "REMOVE", targetId });
  };

  // EDIT
  const onEdit = (targetId, date, content, emotion) => {
    dispatch({
      type: "EDIT",
      data: {
        id: targetId,
        date: new Date(date).getTime(),
        content,
        emotion,
      },
    });
  };
  
  return (...

์ฐธ๊ณ  : https://www.zerocho.com/category/React/post/5fa63fc6301d080004c4e32b

state context

ํ”„๋กœ์ ํŠธ state context ์„ธํŒ…ํ•˜๊ธฐ
์ผ๊ธฐ ๋ฐ์ดํ„ฐ state ๋ฅผ ๊ณต๊ธ‰ํ•  context๋ฅผ ๋งŒ๋“ค๊ณ , provider๋กœ ๊ณต๊ธ‰ํ•œ๋‹ค.

// data state๋ฅผ ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์—ญ์— ๊ณต๊ธ‰
export const DiaryStateContext = React.createContext();

...

return (
  // ์ „์—ญ์— ์ฃผ๊ธฐ ์œ„ํ•ด์„œ provider ๋กœ ๊ฐ์‹ธ์ค€๋‹ค.
  <DiaryStateContext.Provider value={data}>
  	...
  </DiaryStateContext.Provider>



Dispatch context

์ผ๊ธฐ state ์˜ dispatchํ•จ์ˆ˜๋ฅผ ๊ณต๊ธ‰ํ•  context๋ฅผ ๋งŒ๋“ค๊ณ  provider๋กœ ๊ณต๊ธ‰
(state context ์•ˆ์— ๊ณต๊ธ‰ํ•œ๋‹น)

//dispatch ํ•จ์ˆ˜๋“ค๋„ context๋กœ ๊ณต๊ธ‰
export const DiaryDispatchContext = React.createContext();

...

return (
  <DiaryDispatchContext.Provider value={{ onCreate, onEdit, onRemove }}>
 	 ...
  </DiaryDispatchContext.Provider>