Skip to content

altmshfkgudtjr/Simple-React-TS-Template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

31 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Simple React TS Template GitHub license img

This is React-based typescript code that can be quickly generated.

๋น ๋ฅด๊ฒŒ ๋ฆฌ์•กํŠธ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋Š” ํ…œํ”Œ๋ฆฟ์ž…๋‹ˆ๋‹ค.

  • CSS in JS : styled-components๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ปดํฌ๋„ŒํŠธ ๋ณ„๋กœ ์Šคํƒ€์ผ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Hook: ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ธฐ์œ„ํ•ด์„œ Context API ์™€ useReducer ์„ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Build: yarn build๋ฅผ ํ†ตํ•ด์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋“ค์„ production mode๋กœ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ ํ…œํ”Œ๋ฆฟ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ณผ์ •์„ ๋นŒ๋“œ๊ฐ€ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.

    • Pre Build : ์ž‘์„ฑํ•œ ๋ชจ๋“  testํŒŒ์ผ๋“ค์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ, ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•œ ํŒŒ์ผ์ด ์กด์žฌํ•˜๋ฉด ๋นŒ๋“œ๊ณผ์ •์ด ์ง„ํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
    • Build : Sourcemap ํŒŒ์ผ์„ ์ œ์™ธํ•œ ๋นŒ๋“œ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
    • Post Build : ๋ฐฐํฌ๋ฅผ ์œ„ํ•ด์„œ ๋นŒ๋“œ๋œ ํŒŒ์ผ๋“ค์„ '์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•œ ๊ฒฝ๋กœ '๋กœ ๋ณต์‚ฌ๋ฅผ ํ•˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

์œ„ ๊ณผ์ • ๋ฐ '์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•œ ๊ฒฝ๋กœ '๋Š” package.jsonํŒŒ์ผ์—์„œ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

How to run?

yarn install // ํ•„์š” ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.

yarn start	 // HMR(Hot Module Replacement)์ด ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.(๊ธฐ๋ณธํฌํŠธ:3000)
yarn test	 // .test.js๋กœ ๋๋‚˜๋Š” ํŒŒ์ผ์„ ๋Œ€์ƒ์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
yarn build 	 // ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๋นŒ๋“œ๊ณผ์ •์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Directory Structure

Simple-React-Ts-Template
โ”‚
โ”‚  .env
โ”‚  .gitingnore
โ”‚  tsconfig.json
โ”‚  yarn.lock
โ”‚  package.json
โ”‚
โ”œโ”€public
โ”‚  โ”‚  index.html
โ”‚  โ”‚  manifest.json
โ”‚  โ”‚  robots.txt
โ”‚  โ”œโ”€css
โ”‚  โ”œโ”€favicons
โ”‚  โ”œโ”€fonts
โ”‚  โ”œโ”€icons
โ”‚  โ””โ”€images
โ”‚
โ”œโ”€@types
โ”‚      index.d.ts
โ”‚
โ””โ”€src
    โ”‚  App.tsx
    โ”‚  index.tsx
    โ”‚  serviceWorker.ts
    โ”‚  setupTests.ts
    โ”‚  react-app-env.d.ts
    โ”‚
    โ”œโ”€components
    โ”‚  โ”œโ”€home
    โ”‚  โ”‚
    โ”‚  โ””โ”€modal
    โ”‚      โ””โ”€info
    โ”‚  โ””โ”€common
    โ”‚          Snackbar.tsx
    โ”‚
    โ”œโ”€containers
    โ”‚  โ””โ”€modal
    โ”‚          Index.tsx
    โ”‚          info.tsx
    โ”‚  โ””โ”€common
    โ”‚          Snackbar.tsx
    โ”‚
    โ”œโ”€controllers
    โ”‚      index.ts
    โ”‚      fetch.ts
    โ”‚
    โ”œโ”€lib
    โ”‚  โ””โ”€styles
    โ”‚          animations.ts
    โ”‚          media.ts
    โ”‚          palette.ts
    โ”‚          styles.ts
    โ”‚          zIndex.ts
    โ”‚  โ””โ”€utils
    โ”‚          cookieUtil.ts
    โ”‚  โ””โ”€hooks
    โ”‚  โ””โ”€svg
    โ”‚
    โ”œโ”€modules
    โ”‚  โ””โ”€actions
    โ”‚          snackbar.ts
    โ”‚          modal.ts
    โ”‚  โ””โ”€contexts
    โ”‚          snackbar.ts
    โ”‚          modal.ts
    โ”‚  โ””โ”€states
    โ”‚          snackbar.ts
    โ”‚          modal.ts
    โ”‚  โ””โ”€__test__
    โ”‚          modal.test.ts
    โ”‚          snackbar.test.ts
    โ”‚  index.tsx
    โ”‚
    โ”œโ”€pages
    โ”‚      HomePage.js
    โ”‚      NotFound.js
    โ”‚
    โ””โ”€types
       โ””โ”€controllers
               index.ts
       โ””โ”€modules
               snackbar.ts
               modal.ts
    
  • Public: ์ •์  ์ž์›๋ฅผ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ .html, .css, robots.txt ์™ธ์—๋„ ๊ฐ์ข… Image ํŒŒ์ผ๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  • package.json : ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์˜ ์ด๋ฆ„๊ณผ ๋ฒ„์ „ ๋ฐ ํ”„๋กœ์ ํŠธ ์ •๋ณด๋“ค์„ ์ˆ˜์ • ๋ฐ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ PostBuild๊ณผ์ •์—์„œ ๋ฐฐํฌ ํด๋” ๊ฒฝ๋กœ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ ์ฐธ์กฐ)

    "postbuild": "cp -r build/* ../backend/src/client"

    ์ด ์™ธ์—๋„ proxy๋ฅผ ์„ค์ •ํ•˜์—ฌ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•  ๋•Œ, ๊ฐœ๋ฐœ ์„œ๋ฒ„๋ฅผ ๋Œ€์ƒ์„ API๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ http://loclhost:5000์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    "proxy": "http://localhost:5000"
  • tsconfig.json : ํ•ด๋‹น ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ์ปดํŒŒ์ผ ์˜ต์…˜ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (ํ˜„์žฌ ์„ค์ •์€ src๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ ˆ๋Œ€๊ฒฝ๋กœ๊ฐ€ ์„ค์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ์Šคํฌ๋ฆฝํŠธ์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

    import Component from 'components/path/Component'
    
    // or
    
    import Component from '../../components/path/Component'

    3rd-party library ํƒ€์ž…์„ ์„ ์–ธํ•˜๋Š” ํด๋”๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    "typeRoots": [
      "./node_modules/@types",
      "./@types"
    ]
    • ./@types : ํ•ด๋‹น ํด๋”์—์„œ ์จ๋“œํŒŒํ‹ฐ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ช…์˜ ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ , index.d.ts๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • ./@types/index.d.ts : ํ•ด๋‹น ํŒŒ์ผ์—์„œ๋Š” ํ•„์š” ์‹œ, ๋‚ด๋ถ€ ์›์‹œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์˜ค๋ฐ”๋ผ์ด๋”ฉ์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. e.g. window ๊ฐ์ฒด์— ๋Œ€ํ•œ ์˜ค๋ฒ„๋ผ์ด๋“œํ•œ ์ธํ„ฐํŽ˜์ด์Šค Window
  • .env: ํ•ด๋‹น ํ”„๋กœ์ ํŠธ ์‹คํ–‰์— ํ•„์š”ํ•œ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋Š” ํ•ด๋‹น ํŒŒ์ผ์—์„œ ์ถ”๊ฐ€ ๋ฐ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๊ธฐ๋ณธ๊ฐ’์œผ๋กœ, HOST์™€ PORT๊ฐ€ ์ž‘์„ฑ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.)

  • components : View๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

  • containers : View์™€ Store๊ฐ„์˜ Action์„ ๋‹ด๋‹นํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์„ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

  • controllers : API๋“ค์„ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

  • lib : ํ”„๋กœ์ ํŠธ์— ํ•„์š”ํ•œ ์ถ”๊ฐ€ ๋ชจ๋“ˆ๋“ค์„ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

    • styles : Component์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ณตํ†ต style์— ๋Œ€ํ•ด์„œ ๋ชจ์•„๋‘” ํด๋”์ž…๋‹ˆ๋‹ค.
    • utils : Component์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ณตํ†ต ๋กœ์ง์— ๋Œ€ํ•ด์„œ ๋ชจ์•„๋‘” ํด๋”์ž…๋‹ˆ๋‹ค.
    • hooks : ์ปค์Šคํ…€ ํ›…์„ ๋ชจ์•„๋‘” ํด๋”์ž…๋‹ˆ๋‹ค.
    • svg : SVG ํ˜•์‹์˜ ์•„์ด์ฝ˜์„ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค. (index.ts์—์„œ svg๋ฅผ ์ปดํฌ๋„ŒํŠธ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)
  • modules : Reducer๋“ค์„ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

  • pages : ๊ฐ ํŽ˜์ด์ง€๋ฅผ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

  • types : ํ”„๋กœ์ ํŠธ์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํƒ€์ž…๋“ค์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. (ํ•„์š” ์‹œ, importํ•ด์„œ ์‚ฌ์šฉ)

  • __ test __ : (test์™€ __ ์‚ฌ์ด์˜ ๊ณต๋ฐฑ์€ ์—†์Šต๋‹ˆ๋‹ค.) ๊ฐ ์ปดํฌ๋„ŒํŠธ, ๋ชจ๋“ˆ์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•˜๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.

Details

๊ฐœ๋ฐœ ์†๋„๋ฅผ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ ํ•„์ˆ˜์ ์ด๋ผ ์ƒ๊ฐํ•˜๋Š” ๊ธฐ๋Šฅ ๋ฐ ํŒŒ์ผ๋“ค์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

IE Redirect

์ด์ œ๋Š” ์ž˜ ์‚ฌ์šฉ๋˜์ง€์•Š๋Š” Internet Explorer ๋ธŒ๋ผ์šฐ์ €์ผ ๊ฒฝ์šฐ์—๋Š” ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ํŽ˜์ด์ง€๊ฐ€ ํ‘œ์‹œ๋˜๋„๋ก ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ IE๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ํ”„๋กœ์ ํŠธ์ผ ๊ฒฝ์šฐ index.html ํŒŒ์ผ์˜ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ง€์›Œ์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

<!-- index.html -->

<script>
  // Browsers not supported Redirect Page (IE)
  const agent = navigator.userAgent.toLowerCase();
  if ((navigator.appName === 'Netscape' && agent.indexOf('trident') !== -1) || (agent.indexOf("msie") !== -1)) {
  	window.location = "microsoft-edge://" + window.location.href;
  }
</script>

Combined Provider

์—ฌ๋Ÿฌ ๊ฐœ์˜ contexts๋ฅผ ๊ฐ์‹ธ์ฃผ๊ธฐ ์œ„ํ•ด์„œ, ๋ถˆํ•„์š”ํ•œ ์ค‘์ฒฉ๊ตฌ์กฐ๋ณด๋‹ค๋Š”, reduce๋ฅผ ์ด์šฉํ•˜์—ฌ, contexts๋“ค์„ ํ•˜๋‚˜์˜ Provider๋กœ ๋ฌถ์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ modal ๋ฐ snackbar๋ฅผ ์ œ์™ธํ•œ ์ถ”๊ฐ€ contexts๋ฅผ ์ž‘์„ฑ ์‹œ, ์•„๋ž˜ ํŒŒ์ผ์—์„œ contexts๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

// modules/index.tsx

import ModalProvider from 'modules/contexts/modal'
import SnackbarProvider from 'modules/contexts/snackbar'

/*
	Combine Reducers
*/
const CombinedProvider = ({ contexts, children }) => contexts.reduce(
	(Parent, Child) => <Parent>
		<Child>{children}</Child>
	</Parent>
);


/*
	Create Provider
*/
const AppProvider = ({ children }) => {
	return (
		<CombinedProvider contexts={[
			ModalProvider, 
			SnackbarProvider
		]}>
			{children}
		</CombinedProvider>
	);
}

export default AppProvider

Default Modal

๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋‹ฌ์ด ์ž‘๋™ํ•˜๋Š” ํŒŒ์ผ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. useReducer์™€ useContext๋ฅผ ์ด์šฉํ•˜์—ฌ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. (ํ•ด๋‹น ๋ฐฉ์‹์€ ์„ ํƒ์‚ฌํ•ญ ์ž…๋‹ˆ๋‹ค.)

ํŒŒ์ผ์€ containers/modal/info.js ์ด๋ฉฐ, ํ•ด๋‹น ๋ชจ๋‹ฌ์„ ๋ถ€๋ฅด๊ณ  ์‹ถ์€ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ importํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ ํ›„, modal action์— ์กด์žฌํ•˜๋Š” pushModal ์•ก์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋‹ฌ์„ ์ž‘๋™์‹œํ‚ต๋‹ˆ๋‹ค. ๊ฐ ๋ชจ๋‹ฌ์€ ๊ณ ์œ ์˜ id๊ฐ’์„ ๋„ฃ์–ด์„œ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ id๊ฐ’์ด undefined๋ผ๋ฉด ํ•ด๋‹น ๋ชจ๋‹ฌ์€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ๋ฆฌ๋“€์„œ์— ์ž‘์„ฑ๋œ ์•ก์…˜์ž…๋‹ˆ๋‹ค.

// modules/actions/modal

export const pushModal = (id: string, elem: React.ReactNode, args?: any) => ({ type: PUSH_MODAL, payload: { id, elem, args } });
export const popModal = () => ({ type: POP_MODAL });
export const deleteModal = (id: string) => ({ type: DELETE_MODAL, payload: id });
export const clearModal = () => ({ type: CLEAR_MODAL });
  • pushModal : ๋ชจ๋‹ฌ์„ ๋“ฑ๋กํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ์•ก์…˜์„ ํ†ตํ•ด์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ชจ๋‹ฌ์„ ์Šคํƒ์ฒ˜๋Ÿผ ๋“ฑ๋ก์‹œํ‚ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•œ์ฑ„๋กœ ํ™”๋ฉด์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
  • popModal : ๋“ฑ๋ก๋œ ๋ชจ๋‹ฌ์—์„œ ๊ฐ€์žฅ ๋‚˜์ค‘์— ๋“ฑ๋ก๋œ ๋ชจ๋‹ฌ๋ถ€ํ„ฐ ์Šคํƒ์ฒ˜๋Ÿผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • deleteModal : ๋ชจ๋‹ฌ๋ณ„๋กœ ๊ณ ์œ ์˜ id๊ฐ’์„ ์ด์šฉํ•˜์—ฌ ํŠน์ • ๋ชจ๋‹ฌ๋งŒ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • clearModal : ํ˜„์žฌ ๋“ฑ๋ก๋œ ๋ชจ๋“  ๋ชจ๋‹ฌ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋‹ฌ์„ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์€ ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

import { useContext } from 'react'
import styled from 'styled-components'
// containers
import InfoModal from 'containers/modal/Info'
// modules
import { modalContext } from 'modules/contexts/modal'
import { pushModal } from 'modules/actions/modal'

const Btn = () => {
	const { dispatch: modalDispatch } = useContext(modalContext);
	
	const modalOn = () => modalDispatch(
		pushModal('INFO', InfoModal, {title: "Simple"})
	);

	return <Button onClick={modalOn}>Simple</Button>
}

const Button = styled.button`
	...
`;

export default Btn

ํ•ด๋‹น ๋ชจ๋‹ฌ ํŒŒ์ผ์—์„œ๋Š” PreventModalOff ์™€ ModalOff ๋ฐ args ์ธ์ž๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. PreventModalOff ํ•จ์ˆ˜๋Š” onMouseDown ์†์„ฑ์œผ๋กœ ๋ชจ๋‹ฌ ์ตœ์ƒ์œ„ ์†์„ฑ์— ๋“ฑ๋กํ•ด์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค. ModalOff๋Š” ์„ ํƒ์  ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. args๋Š” ๋ชจ๋‹ฌ์„ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ชจ๋‹ฌ์—๊ฒŒ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ Background์— MouseDown ์ด๋ฒคํŠธ๋กœ ๋ชจ๋‹ฌ์ด ๋‹ซํžˆ๋„๋ก ์ž‘๋™๋ฉ๋‹ˆ๋‹ค. ์ด ์™ธ์— ๋ฒ„ํŠผ์„ ํ†ตํ•ด์„œ ๋ชจ๋‹ฌ์„ ๋‹ซ๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

Default Snackbar

๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด๋‹ค ๋‚˜์€ Alert ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด์„œ Snackbar ๊ตฌ์กฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณธ ์Šค๋‚ต๋ฐ”๋Š” useReducer์™€ useContext๋ฅผ ์ด์šฉํ•˜์—ฌ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. (ํ•ด๋‹น ๋ฐฉ์‹์€ ์„ ํƒ์‚ฌํ•ญ ์ž…๋‹ˆ๋‹ค.)

๊ธฐ๋ณธ์ ์œผ๋กœ ์Šค๋‚ต๋ฐ” ํƒ€์ž…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. (Type : Default Color)

export type SnackbarType = 'INFO' |'SUCCESS' |'WARNING' |'ERROR';
  • SUCCESS : Green Color
  • WARNING : Red Color
  • ERROR : Orange Color
  • INFO : Gray Color

์Šค๋‚ต๋ฐ”๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์€ ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

/* This file is Sample Component to call a snackbar. */

import { useContext } from 'react'
// components
import Button from 'components/path/Button'
// modules
import { snackbarContext } from 'modules/contexts/snackbar'
import { newSnackbar } from 'modules/actions/snackbar'


const Btn = () => {
	const { dispatch: snackbarDispatch } = useContext(snackbarContext);
	const callSnackbar = () => newSnackbar(snackbarDispatch, 'ํ…Œ์ŠคํŠธ ๋ฌธ๊ตฌ', 'INFO');

	return <Button onClick={callSnackbar}>Snackbar</Button>
}

export default Btn

Default Fetch file

๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„๋™๊ธฐ ํ†ต์‹ ์„ ์œ„ํ•ด์„œ fetch API๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ํŒŒ์ผ์—์„œ๋Š” CRUD๋ฅผ ๋งŒ์กฑํ•˜๋Š” API๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (๋ณธ ํŒŒ์ผ ์‚ฌ์šฉ์œ ๋ฌด๋Š” ์„ ํƒ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์ง€์›Œ์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.)

const Fetch = <T = any, U = object | FormData>(
	url: string,
	method: apiType.HttpMethod,
	sendData?: U,
	callback?: (res: apiType.FetchResultExtended<T>) => void,
	failed?: (res: apiType.FetchResultExtended<T>) => void
): Promise<apiType.FetchResultExtended<T>> => { ... };

๊ธฐ๋ณธ์ ์œผ๋กœ ํ•ด๋‹น ๋ชจ๋“ˆ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ธ์ž๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  • url: Target url์ž…๋‹ˆ๋‹ค. ์˜ˆ์‹œ) /board/1/post/3

  • method : ๊ธฐ๋ณธ์ ์œผ๋กœ API๋Š” REST API ๋ฉ”์†Œ๋“œ๋ฅผ ์ค€์ˆ˜ํ•˜์—ฌ ํƒ€์ž…์„ ์ง€์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‹ค๋ฅธ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ํ•ด๋‹น ํƒ€์ž…์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. POST, GET, DELETE, PUT, PATCH ๋“ฑ์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

    // REST API Method
    type HttpMethod = 'POST' | 'GET' | 'PUT' | 'DELETE' | 'PATCH';
  • sendData : HTTP ์š”์ฒญ์„ ํ•  ๋•Œ, ํ•„์š”ํ•œ data์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ json/application์œผ๋กœ ๋ณด๋‚ด์ง€๋ฉฐ, sendData๋Š” JSONํ™” ๋˜์–ด์„œ ํ†ต์‹ ์ด ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. FormData ํƒ€์ž…๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

  • callback : ํ†ต์‹ ์ด ์™„๋ฃŒ๋œ ํ›„์— ์‹คํ–‰๋  ์ฝœ๋ฐฑํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์„ ํƒ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

  • failed : 4xx ๋˜๋Š” 5xx ์—๋Ÿฌ(๋Œ€ํ‘œ์ ์œผ๋กœ 404, 502)๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ, ์‹คํ–‰๋  ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์„ ํƒ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

headers๊ฐ’์˜ Accept ์†์„ฑ์— 'application/json' ์„ ์ ์šฉํ•˜์—ฌ, ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๊ฐ API๋ณ„ json ๋ฉ”์„ธ์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, server์œผ๋กœ๋ถ€ํ„ฐ ๋ฐ›๋Š” ๋ฐ˜ํ™˜๊ฐ’์— ๋Œ€ํ•œ ๊ทœ์•ฝ์ด ์กด์žฌํ•  ๊ฒฝ์šฐ FetchResultExtended ํƒ€์ž…์„ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

/**
 * API Return Type (Origin)
 */
export interface FetchResult<T> {
	verify: boolean;
	message: string;
	result: T;
}

/**
 * API Return Type (Extended)
 * - Add HTTP Status Code
 */
export interface FetchResultExtended<T> extends FetchResult<T> {
	statusCode: number
};

๋น„๋™๊ธฐ ํ†ต์‹ ์œผ๋กœ ๋ฐ›์€ ๋ฐ์ดํ„ฐ์˜ ํƒ€์ž…์„ Fetch๋ฅผ ์‹คํ–‰ํ•  ๋•Œ, ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

Fetch<{name: string, birth: number}>('/api/auth/user', 'GET')

Generic ํƒ€์ž…์„ ์ •์˜ ์—ฌ๋ถ€์˜ ์ฐจ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ˜ํ™˜๋ฐ›์€ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด์„œ ํƒ€์ž… ์ถ”๋ก ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์„ ์–ธํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ any ํƒ€์ž…์œผ๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค.

Fetch

ํ•ด๋‹น ๋ชจ๋“ˆ์€ Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

import Fetch from './fetch'

Promise.all([
  Fetch('/api/first', 'POST', {'key': 'value'}),
  Fetch('/api/second', 'POST', {'key': 'value'}),
  Fetch('/api/third', 'POST', {'key': 'value'})
]);

// or (Using Promise .then/.catch)

Fetch('/api/first', 'GET')
.then(data => {
   console.log(data); 
})
.catch(err => {
    console.log(err);
});

// or (Using Callback)

Fetch('/api/first', 'POST', {'key': 'value'}, 
(data) => {
  console.log(data);
},
(err) => {
  console.log(err);
});

Fetch('/api/first', 'POST', {'key': 'value'}, 
function(data) {
  console.log(data);
},
function(err) {
  console.log(err);
};

// Top-Level await ๋ฌธ๋ฒ•์€ Typescript 3.8 RC ๋ฒ„์ „๋ถ€ํ„ฐ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
const response = await Fetch('/api/first', 'GET');

Feedback & Issue

ํ”ผ๋“œ๋ฐฑ ๋ฐ ์ด์Šˆ ์ œ๊ธฐ ๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์ด๊ฑฐ๋‚˜ ๋ถˆํ•„์š”ํ•œ ๊ธฐ๋Šฅ์ด๋ผ๊ณ  ์ƒ๊ฐ๋œ๋‹ค๋ฉด, ์–ธ์ œ๋“ ์ง€ Issue๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค!

'

About

This is React-based typescript code that can be quickly generated.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published