2021년 03월 20일
styled-components를 사용하는 도중 defaultProps 타입 오류가 발생했다. Props 전달에도 이상이 없었고 어떤 오류인가 싶어서 검색해봤다. Type of property 'defaultProps' circularly references itself in mapped type TypeScript Github에 등록된 이슈를 확인해보니, 정확하지는 않지만 Typescript^3.9.0 이후 나타나며 해당 오류는 styled-components에서 5.0.1 버전대에서 fix 되었다. ( 자세한 사항은 하단 참고자료로 이동하여 확인하면 좋을 것 같다. ) yarn upgrade @types/styled-components --latest # or npm install @types/styled-components@latest styled-components의 type을 업데이트하는 방법이 있으며, 어려운 경우에는 styled-components.d.ts를 생성하여 예외처리 하는 방향도 있다. 참고자료 https://github.com/microsoft/TypeScript/issues/37597#issuecomment-628149946
2021년 03월 09일
Grafana Plugin을 React로 개발하여 배포하는 방법을 설명한다. 작업환경 OS: Mac node: >= 14.0 grafana: >= 7.0 시작하기 Grafana 설치하기 Grafana 설치 가이드 문서 Ubuntu, Docker 등 OS 별 설치방법 문서가 존재한다. brew update brew install grafana Grafana 프로젝트 생성 프로젝트 구조는 grafana-toolkit를 사용한다. grafana-toolkit은 creact-react-app 처럼 초기 프로젝트를 구축하기 위한 CLI이다. 맨 설치하는 과정에서 plugin, author 등은 원하는 형태에 맞춰서 작성하면 되며, 플러그인 이름은 신중하게 입력해보자. npm install -g @grafana/toolkit npx @grafana/toolkit plugin:create [project-name] cd graph-plugin npm install ( 프로젝트를 grafana에 연동하는 부분은 아래에서 진행한다. ) 실행하기 설치한 grafana 서비스를 실행한다. brew services start grafana 기본적으로 localhost:3000로 포트가 열린다. 초기 계정은 admin/admin 이다. 개발셋팅 프로젝트를 생성했고 grafana service 가 동작한다면, 프로젝트를 플러그인에 연동해야한다. grafana ini 설정 grafana 설정파일에서 plugin path를 연결한다. vim /usr/local/etc/grafana/grafana.ini [paths] plugins = [Grafana Project Path] 이때, [paths] 아래에 추가해야한다. 맨 상단 혹은 맨 하단에 작성 시 작동되지 않는다. 실행하기 설치한 grafana 서비스를 재실행한다. brew services restart...
2020년 01월 17일
채팅과 같이 메시지가 도착하면 최하단으로 계속 이동해야하는 경우나 단순 최하단으로 이동하고 싶을 때 구현하는 방법입니다. 자바스크립트에서 스크롤 하단으로 이동 엘리먼트의 height만큼 scroll 위치를 이동합니다. // overflow 스크롤이 걸려있는 엘리먼트 const ele = document.querySelector("ul"); ele.scrollTop = ele.scrollHeight; React에서 응용하기 React에서 채팅 레이아웃에서 메시지가 들어올 때마다 최하단으로 이동하는 코드입니다. import React, { useRef, useEffect } from 'react'; import { useMessages } from 'Hooks'; ... const messagesRef = useRef<HTMLUListElement>(null); // 메시지 엘리먼트를 저장 const { messages } = useMessages(); // Custom Hooks : 메시지 리스트 useEffect(() => { messagesRef.current!.scrollTop = messagesRef.current!.scrollHeight; }, [messages]); ... return ( <ul className="messages" ref={messagesRef}> {messages.map(message => { return ( <li key={message.key}> ... </li> ); })} </ul>; ) firebase를 사용하고 있으며, 메시지를 구독하면 useMessages에서 messages를 내려줍니다. 이후 messages가 업데이트될 때 마다, ul 엘리먼트를 최하단으로 이동합니다. 만일 특별하게 최하단으로 이동하기 싫으시다면, useEffect 내에 if문으로 조건을 설정하시면 됩니다.
2020년 01월 06일
이전 프로젝트에서는 webpack을 eject하여 CSS module을 사용했지만, 이번 프로젝트에서는 eject 작업을 하지 않고 진행하기 때문에 방법을 찾아보았다. CSS Module 적응 전에는..? Module을 적용하지 않는다면, 최상단 App.jsx 또는 컴포넌트에서 scss 파일을 호출합니다. // index.tsx or App.tsx import "./index.scss"; 또한 클래스명이 기존 html처럼 class=”container” 형태로 들어가기 때문에 css/scss 파일을 컴포넌트별로 생성했음에도 스타일 명이 충돌하는 불편함이 있습니다. 그렇다면 CRA에서 CSS Module은 어떻게 적용하지? css/scss 파일명을 module.css, module.scss로 변경합니다. 예를들어 index.scss는 index.module.scss 가 됩니다. 이후 컴포넌트에서는 다음과 같이 사용합니다. import React from "react"; import styles from "./index.module.scss"; ... return ( <div id={styles.container}> <div className={styles.messageWrap}> </div> </div> ) ... scss는 기존처럼 사용하시면 되며, id, class의 컴파일 결과를 확인하시면 scss 파일의 이름 혹은 폴더 이름으로 유니크하게 생성된 것을 확인할 수 있습니다. 아래는 컴파일 결과의 예시입니다. // components/Pages/index.module.scss #loginPage { display: block; } // components/Pages/LoginPage.tsx import styles from "./index.module.scss" ... return ( <div id={styles.loginPage}> ); => <div class="Pages_LoginPage__2Jrev" />
2019년 12월 12일
Nextjs에서 styled-components (이하 SC) 사용하면 CSS 로딩이 늦게 되어 발생하는 깜빡임 현상이 발생합니다. 개인적인 생각으로는 HTML은 SSR로 미리 렌더링 시켜 보내지만 SC의 스타일들은 사용자가 접속 시 변환된다고 생각합니다. css를 미리 적용할 수 있을까? 참고 자료 Next.js와 SC를 검색한 결과, ServerStyleSheet라는 함수를 SC에서 제공하고 있었고 Next.js에서 샘플 코드를 제공하고 있었습니다. 해당 페이지에서 제공하는 코드는 다음과 같습니다. import Document from "next/document"; import { ServerStyleSheet } from "styled-components"; export default class MyDocument extends Document { static async getInitialProps(ctx) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; try { ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: ( <> {initialProps.styles} {sheet.getStyleElement()} </> ), }; } finally { sheet.seal(); } } } _document.js 란? HTML Document를 관리하는 부분으로 이 외에도 '_app.js, _error.js' 등이 있습니다. 위 코드에서 에러가 나신다면..? 시간이 지나고 작성하는 글이라 정확하게 기억은 안나지만, 위에 코드를 사용해도...
2019년 12월 11일
2019년 초에 Redux를 사용하다가 불편함이 많아 useContext를 사용법을 찾아봤을 때 자료가 생각보다 많지 않아 헤맸던 기억이 있습니다. 늦었지만, useContext의 활용법을 공유 드립니다. createContext로 생성하자 import React, { createContext } from "react"; export const AppContext = createContext(); 우선 Context를 생성합니다. 초기화는 바로 할 필요 없으며, export하는 이유는 Redux처럼 다른 파일에서 접근하기 위해 정의합니다. context에 함수와 데이터를 저장하자 const App = () => { const [text, setText] = useState("test"); const logText = (text) => { console.log("test"); }; return ( <AppContext.Provider value=> <ViewLayout /> </AppContext.Provider> ); }; export default App; Provider를 선언하게 되면, 해당 Provider의 자식들은 value에 선언된 부분들을 props로 넘겨주지 않아도 사용할 수 있습니다. ViewLayout에서 useContext를 사용하여 데이터 및 함수 실행을 진행합니다. useContext로 호출하자 import React, { useContext } from "react"; // App에 선언 된 context 호출 import { AppContext } from "./App"; const ViewLayout = () => { const { text, setText, logText } = useContext(AppContext); return ( <div> <div>{text}</div> <button...
2019년 12월 11일
동영상 플레이어 중 영상의 비율을 맞춰주기 위해 영상의 세로가 긴 화면은 양쪽에 검은색 여백이, 영상의 가로가 긴 화면은 상하단에 검은색 여백이 생성되는 플레이어들이 있습니다. 검은색 여백은 video 태그에 width: 100% or height:100% 중 어떤 속성인지로 적용됩니다. 여기서 video 태그를 감싸고 있는 div보다 video 태그의 height가 높아지면 height를 100%로 고정하여 양 옆에 여백을 생성하고, width가 높아지면 width를 100%로 고정하여 상하에 여백을 생성합니다. 동영상의 비율을 수정하자 useRef를 사용해도 무방합니다. useLayoutEffect를 사용하여 화면의 resize를 감지하고 함수를 실행합니다. updateSize 함수에서 video 사이즈와 video-wrap 사이즈를 비교하고 클래스를 적용합니다. contains로 현재 클래스를 비교한 이유는 이미 적용되어있기 때문에 if문을 거쳐도 변화가 없기 때문입니다. import React, { useLayoutEffect } from "react"; const Video = () => { const updateSize = () => { const videoWrap = document.querySelector("#video-wrap"); const video = document.querySelector("#video"); if ( !video.classList.contains("is-vertical") && video.offsetHeight > videoWrap.offsetHeight ) { video.classList.add("is-vertical"); } else if ( video.classList.contains("is-vertical") && video.offsetWidth > videoWrap.offsetWidth ) { video.classList.remove("is-vertical"); } }; useLayoutEffect(() => {...
2019년 12월 02일
Github에서 리액트 앱을 공유할 때, 서버 없이 간단하게 Github Page로 공유가 가능합니다. gh-pages 모듈 설치 yarn add --dev gh-pages package.json 수정 gh-pages 모듈을 설치 후 package.json에서 아래 내용을 추가해주세요. { ... "homepage": "/${path}", "scripts": { ... "predeploy": "yarn build", "deploy": "gh-pages -d build" } } gh-pages 배포 yarn run deploy 만약 deploy 명령어로 배포 시 gh-pages 브랜치를 생성하는 과정에서 오류가 발생할 수도 있다. git branch로 조회해도 없는 gh-pages가 이미 존재한다는 오류는 새롭다.. 이럴 때는 당황한 뒤에 gh-pages 브랜치를 직접 생성한 후 push 해보자. git checkout -b gh-pages git push --set-upstream origin gh-pages yarn run deploy 확인 배포가 완료되면, gh-pages branch가 생성되어 있습니다. Github에서 해당 프로젝트로 이동 후 Settings -> 하단 GitHub Pages 메뉴를 보시면 배포 된 깃헙 페이지 링크를 확인할 수 있습니다.