React

useReducer로 useState 리팩터링 하기 (3)
simpleSymbols = [ {"PAUSE"}, {"ENTER"}, {}, {"MOUSE", "SLASH"}, ... , {} ] 각 단어마다 어떤 기호가 포함되어 있는지 저장하기 위해 위와 같은 방법을 사용한 이유는 다음과 같다. 기호들을 reducer로 묶으면서, 같은 로직을 기호의 이름만 달리 해서 실행할 수 있어야 했다. 사용자가 같은 기호를 여러 번 적용하더라도 중복 없이 하나만 저장해야 한다. 각 기호별로 단어 수만큼의 길이를 가진 배열을 저장하는 것보다 저장공간이 절약된다. 새로운 기호를 추가하더라도 기존 코드를 변경 할 필요 없이 해당 기호의 이름만 추가하면 된다. 기호들을 렌더링 할 때 각 단어마다 전체 기호 수 만큼의 비교 연산을 수행할 필요가 없다(set에 있는 단어들을 그냥 모두..

useReducer로 useState 리팩터링 하기 (2)
useReducer에 대해 이론적인 부분만 공부하고 바로 리팩터링을 도전했더니 예상치 못한 이슈가 많이 발생했다. 1. 상태 업데이트 안됨 const simpleSymbolsReducer = (state, action) => { switch (action.type) { case "INIT": return action.payload; case "ADD": return state.map((symbol, i) => { if (i === action.idx) { return new Set([...symbol, action.symbol]); } else { return symbol; } }); case "REMOVE": return state.map((symbol, i) => { if (i === action.i..
useReducer로 useState 리팩터링 하기 (1)
원래 useState로 관리하던 사용자 기호들 중 작동 방식이 비슷한 도구들을 묶어 reducer로 관리하기로 했다. const [enterSymbol, setEnterSymbol] = useState([]); const [pauseSymbol, setPauseSymbol] = useState([]); const [mouseSymbol, setMouseSymbol] = useState([]); const [slashSymbol, setSlashSymbol] = useState([]); ... case 4: enterSymbol[selectedWordIdx] = true; setEnterSymbol([...enterSymbol]); break; case 5: pauseSymbol[selectedWordId..
useReducer
useReducer는 reducer를 사용할 수 있도록 하는 리액트 내장 훅이다. 현재 스피치의 스크립트를 편집하고 재생하는 컴포넌트에 너무 많은 상태들이 useState로 관리되고 있어서, 업데이트 로직이 비슷한 상태들을 reducer로 묶어보려고 한다. 그래서 우선 useState로 관리하던 상태들을 useReducer로 리팩터링하는 과정에 집중해서 알아볼 것이다. 상태를 업데이트 하는 로직을 하나의 함수로 컴포넌트와 분리할 수 있는데, 이것을 reducer라고 한다. reducer를 다른 파일로 분리해 사용할 수도 있으며 코드가 복잡해 질 수록 유용하다. useReducer는 reducer function과 initial state 두 개의 인자를 갖고, stateful value와 dispatch..
useEffect로 state 변경 바로 감지하기
이전 글에서 함수가 끝날 때까지 state의 값은 변하지 않는다는 것을 배웠다. 그렇다면 한 함수 안에서 state를 변경하고, 그 값을 바로 사용해야 한다면 어떻게 해야 할까? 내가 고민한 코드는 아래 코드였다. const handleBlur = useCallback( (e, i) => { let updated = [...edited]; if (e.target.innerText === text[i]) { updated[i] = null; } else if (e.target.innerText.trim() === "") { updated[i] = "-"; } else { updated[i] = e.target.innerText; } setEdited(updated); // patchUserSymbol();..
State 작동 방식
그동안 state의 작동 방식에 대해 제대로 이해를 못한 채로 코드를 짜서 기능이 내 의도와 다르게 돌아간 적이 많았다. setState를 사용하면 state 값이 바로 바뀌고 해당 state를 그려주는 부분이 다시 그려진다고만 알고 있었는데, 자세히 들여다보니 그게 아니었다. const [ count, setCount ] = useState(0) function onClickCountUp() { setCount(5) } return ( {count} 카운트 ) 위 코드의 동작 방식은 다음과 같다. 버튼을 클릭하면 setCount() 함수가 실행됨 → setCount: count 값 비교 (같으면 무시) 다르면 count 값을 5로 바꾸기 화면 다시 그리기(리렌더링) → 위에서부터 하나씩 다시 실행 변수..

styled component에 css animation 적용 (재생되는 텍스트 만들기)
styled component에 keyframe을 이용해 animation을 적용하려면 keyframes를 따로 import 해줘야 한다. import styled, { keyframes } from "styled-components"; 그리고 다른 styled component를 선언할 때와 마찬가지로 keyframe을 만들어 준다. const PlayingText = keyframes` ... } `; 이번에 개발한 기능은 음성 파일이 재생될 때 시간에 따라 (노래방 기계처럼) 색이 입혀지는 텍스트였다. 단순히 텍스트의 색을 지정하기 위해서는 css의 color 속성을 사용하면 된다. 하지만 이렇게 그라데이션을 넣거나, 이렇게 이미지를 텍스트의 배경으로 쓰고 싶다면 어떻게 해야 할까? backgrou..
Error Boundary
이번 주 플젝 중 백엔드 팀원들이 에러 핸들러를 만들면서 고생하는걸 지켜봤다. 클라이언트에서는 서버에서 보내주는 상태 코드를 처리하거나 자체 에러를 핸들링 할 때 어떻게 해야 할까? Error Boundary React 공식 문서 Component – React The library for web and native user interfaces react.dev 레거시로 분류되어 있는 error boundary.. 그러나 카카오페이지에서 사용한다는걸 보고 그냥 쓰기로 했다 ㅎ 리액트는 렌더링 중에 에러가 생기면 화면에서 UI를 지워버린다. 이걸 "컴포넌트가 깨진다"고들 표현한다. 즉, 에러가 생긴 컴포넌트만 언마운트 되는 게 아니라 모든 컴포넌트가 언마운트 되는 것이다. 잘못된 정보를 사용자에게 보여 주..