간단한 과제 소개todoList 형태의 메달(금, 은, 동) 데이터 관리 페이지국가 및 메달 개수 입력 가능입력한 국가별 메달 현황 확인입력, 삭제, 수정, 정렬페이지 레이아웃은 위와 같다. 상단에 데이터를 입력, 수정할 수 있는 폼이 있고 하단에 테이블 형태로 list를 확인할 수 있다. list 영역에서 반복가능한 데이터는 크게 2가지가 있다. 첫 번째는 헤더 부분 "국가명 금 은 동 액션"이 있고 두 번째는 각 나라별 데이터 목록이다. 우선 두 번째 데이터 목록 부분부터 어떻게 반복시킬수 있을지 살펴 보자. 💡 행 반복 + 열 반복 - Object.values()데이터 한 줄 한 줄이( "미국 132 0 0 버튼" ) 하나의 행이다. 전체 데이터 구조는 배열내의 객체들로 이루어져 있다. coun..
💡 전역 상태관리 - Redux📍 useState의 불편함 컴포넌트의 state를 공유할 때 Props를 통해 부모 컴포넌트에서 자식 컴포넌트로 전달하게 된다. 아니 그래야만 한다. 1. 반드시 부모-자식 관계가 되어야 공유가 가능하다.2. prop drilling이 발생하고 불필요한 코드가 생긴다. (props를 받아서 전달만 하는 컴포넌트는 불필요하다.)3. 자식 컴포넌트에서 부모 컴포넌트로 값을 보낼 수 없다. 📍 리덕스를 사용하면state를 공유할 때 부모-자식 관계가 아니어도 된다중간에 의미 없는 props의 전달 과정이 없어도 된다. 자식 컴포넌트에서 만든 state를 부모 컴포넌트에서 사용이 가능하다. 💡 Global state & Local StateGlobal state는 redu..
배포 시 프로젝트의 `public` 폴더에 넣은 자료(이미지, 폰트 등)는 자동으로 최상위(루트)경로로 인식이 된다. 예를 들어 사진이 `/public/assets/logo.png` 라는 경로에 존재할 경우 다음과 같이 매핑을 시켜주면 된다.`src="/assets/logo.png"` (`public` 생략)
일반적으로 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 `props`를 사용해서 전달한다. 하지만 깊이가 깊어질 수록 prop drilling이 발생한다. 쉽게 말해 드릴로 뚫어버리듯 prop의 전달이 너무 깊어진다는 의미이다. 아래 발로 만든 구조를 보자. 대충 저런 구조에서 더 타고 내려가면 어떤 문제가 발생할까? 사실 아무런 문제도 발생하지 않는다. 물론 컴퓨터가 해석 할 때 아무 문제가 생기지 않는다는 것이고, 사람이 인지하는데는 어려움이 발생할 수 있다. 문제점깊이가 깊어질수록 어떤 컴포넌트로부터 props가 내려왔는지 파악이 어렵다. 특정 컴포넌트에서 오류가 발생할 경우 디버깅이 어려워진다. prop drilling의 예시 코드를 작성해보고 후에 context를 사용해서 리팩토링..
💡값이 변경될 때 리-렌더링useState와 useRef의 가장 큰 차이는 값이 변경될 때 렌더링의 발생 유무이다. State는 값이 변경될 때마다 리렌더링이 되지만 Ref는 리렌더링이 되지 않는다. Ref는 리렌더링이 될 때 변경된 값을 확인할 수 있다. 따라서 컴포넌트에 엄청 자주 변경되는 값이 있을 때, 그 값에 의해 리렌더링될 필요는 없을 때 사용하면 좋다. 일반 변수와도 닮은 것 같지만 리렌더링이 될 때 컴포넌트 자체가 다시 호출되게 되고 이 때 일반 변수는 값이 다시 초기화 되지만 Ref는 컴포넌트의 전생애주기(마운트 ~ 언마운트)를 통해 유지되기 때문에 컴포넌트가 리렌더링 되어도 값을 유지한다. 💡 DOM 요소에 접근할 때자바스크립트에서 id나 class등으로 DOM 요소에 접근하는..
리액트는 자식 컴포넌트에 값을 전달할 때 props라는 녀석으로 전달하게 된다. props는 전달한 인자를 통으로 묶은 객체 형태로 전달이 된다. 예시 코드// 부모// 자식const 자식 = (props) => { console.log(props) // 출력: {name: '길동', age: 30}}객체로 전달한 적이 없으나 props라는 객체 안에 내가 전달한 변수들이 들어있는것을 확인할 수 있다. 💡 객체를 하위 컴포넌트로 전달위 처럼 간단한 데이터를 보내는게 아니고 객체를 보내야 한다면 아래와 같은 구조로 props를 받아올 것이다. obj = {name:'길동', age: 30}const 자식 = (props) => { const name = props.obj.name; const ag..
react에서는 각종 컴포넌트를 미리 만들어 놓고 필요에 의해 호출하여 사용한다. 반복되는 컴포넌트는 반복문을 통해 호출하게 되는데 이 때 각 컴포넌트에 `key` 를 지정할 수가 있다. 💡 keykey는 반복문으로 호출되는 컴포넌트에 전달(포함)시키는 값이다. 리스트로 이루어진 컴포넌트 중에서 값의 변화가 이루어지는 컴포넌트를 식별하기 위해서 사용한다.즉, `key`가 없으면 컴포넌트를 순회하여 변화를 감지한 이후에 리렌더링을 하게 되고 성능적으로 좋지 않다.각각의 컴포넌트에 고유한 값을 전달해야 한다. `key`를 직접 명시하지 않으면 자동으로 인덱스를 `key` 로 사용한다.
useState로 값을 업데이트 하는 방식은 일반형과 함수형 두 가지가 있다. 💡 (1) 일반형 업데이트 count 값에 +1 을 더해주는 간단한 예시 코드 const [count, setCount] = useState(0);setCount(count + 1); // 일반형많이 사용되는 방법이고 간결하다. 하지만 하나의 함수에서 여러번의 값이 변경되어야 할 때 문제가 생길 수 있다. 다음 코드를 봅시다. const [count, setCount] = useState(0);/* 어쩌구 저쩌구 코드들 */ { setCount(count + 1); setCount(count + 1); setCount(count + 1); }}>+3버튼을 한 번 클릭할 때마다 `count + 1` 을 ..
💡 useEffect()const [count, setCount] = useState(1);const handleCountUpdate = () => { setCount(count + 1);}const handleInputChange = (e) => { setName(e.target.value);}/* 대충 다른 코드들 */return ( 추가 count: {count} name: {name})`count`와 `name` 값이 이벤트에 따라 handle 함수들에 의해 업데이트되는 저런 코드가 대충 존재함. 저렇게 업데이트 되거나, 마운트(최초 렌더링)되거나, 마운트가 해제되었을 때 실행되는 것이 `useEffect()` 임 사용 예시 (1) - 모든 state의 변경에 대해 실행const ..
💡 지연 초기화기본적으로는 useState에 초기값을 넣어주게 되면 state가 뭐 어떻게 변하건 초기값을 계속 불러오게 된다. 하지만 Lazy initialzation 기법(?) 을 사용하면 처음 렌더링 될 때만 호출(동작)된다. 원래 쓰던 방법const getName = () => { /* 막 api 불러오고 */ /* 막 데이터 가공하고 */ /* 막 데이터 정렬하고 */ /* 기타 무거운 코드들 */ return 전국민이름모음}const [name, setName] = useState(getName());초기값으로 getName()에서 반환된 값을 사용한다. 가벼운 작업이나, 상수값 같은 것들은 그냥 써도 되겠지만 혹시 저렇게 작업량이 많고 무거운 값을 반환받아 사용될 경우 성능적인..
ESLint를 설치하고 React 프로젝트를 하다보면 자꾸 뭐 prop 어쩌구 거슬리게 하는 친구가 있다. 프로젝트 root경로에 있는 `eslint.config.js` 파일을 잠깐 손봐주도록 하자. 그럼 rules : { .... } 속성이 보일텐데 여기에 아래 텍스트만 하나 추가해주면 된다 ."react/prop-types": "off" 전체 rules rules: { ...js.configs.recommended.rules, ...react.configs.recommended.rules, ...react.configs['jsx-runtime'].rules, ...reactHooks.configs.recommended.rules, 'react/j..
간략한 팀프로젝트 소개tmdb api를 이용하여 다양한 영화 정보를 가져올 수 있다. 가져온 영화 정보를 이용해서 다양한 기능과(검색, 평점, 댓글 등) 디자인 적인 부분까지 신경써서 제작한 프로젝트이다. 이전 리팩토링 과정(1) - [불어나는 API_URL 관리](2) - [중복되는 매개변수 제거](3) - [spread & rest](4) - [불어나는 코드 모듈로 분리]이번 리팩토링은 고정으로 사용되는 초기값, 상수값 등을 상수로 선언하도록 변경했다. 💡 기존 코드function getSlicedOverview(overview) { if (!overview) return "줄거리가 없는디" if (overview.length >= 80) { return `${overview.slice..