[23.10.05] 44일차
- 체계적인 사고
- 문제해결 능력
- 기술학습 능력
<< React.js 활용 SPA 애플리케이션 개발 >>
0919 : 0일차 - 2시간 (HTML + CSS활용)
0920 : 1일차 – JavaScript 기본
0921 : 2일차 – JavaScript 기본
0922 : 3일차 – JavaScript 기본
0925 : 4일차 – JavaScript 기본 (happymarket)
0926 : 5일차 – JavaScript 기본 (happymarket)
0927 : 6일차 – React
1004 : 7일차 - React
1005 : 8일차 - React
1006 : 9일차 - React node.js
<<진도>>
Front-end
- [React]
- local storage
- json 정의로 local storage에 편하게 저장하기
- 배포 (github, git, repository 원격저장소)
- 배열 함수 array function
- 모듈 module (외부 파일문법)
<< 과제 >>
- 하트 클릭시 숫자 1부터 증가하게
<<오늘의 팁>>
- [로컬 스토리지 저장목적]
: JSON.parse() : json 파일을 js 형태로 변환 < localstorage.getItem() >
: JSON.stringify : js를 json에 맞는 형태로 형변환 < localstorage.setItem() >
- JS에서 NaN : 연산불가일때도 뜬다.
- (왼쪽요소) || (오른쪽요소) : 왼쪽요소가 null / false / NaN 등이면 오른쪽쓰기
- (VScode) ctrl + ` : 터미널 창 on/off
** JS <-> JSON을 간편하게 사용하기
//////// JSON 간편하게 사용하기
// global scope
const jsonLocalStorage = {
setItem: (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
},
getItem: (key) => {
return JSON.parse(localStorage.getItem(key));
},
};
웹브라우저의 DOM과 리액트 DOM은 다름
리액트가 가상DOM(VDOM)을 만들어서 웹HTML DOM과 비교하여 변경된 것 만 웹에 반영(표현): re-redering
[리렌더링 시]
** 동작 때마다 상태값이 초기화나 값이 변하지 않아도
계속 local storage 접근(getItem) 실행됨(비효율적)
const [favorites, setFavorites] = React.useState(jsonLocalStorage.getItem('favorites') || []);
const [counter, setCounter] = React.useState(jsonLocalStorage.getItem('counter'));
** 상태를 (익명함수)화살표함수로 만들면 리렌더링 시
초기화 때 한 번만 접근 (set만 된다.)
const [favorites, setFavorites] = React.useState(() => {
console.log('[favorites 상태 초기값 설정]');
return jsonLocalStorage.getItem('favorites') || []
});
const [counter, setCounter] = React.useState(() => {
console.log('[counter 상태 초기값 설정]');
return jsonLocalStorage.getItem('counter')
});
** state set도 익명함수 형태로 바꾸기
function updateCounter(event) {
const nextCounter = counter + 1;
setCounter(nextCounter);
jsonLocalStorage.setItem('counter', nextCounter);
}
setCounter()와 setItem()을 함께 관리하는법
function updateCounter(event) {
// const nextCounter = counter + 1;
// setCounter(nextCounter);
// jsonLocalStorage.setItem('counter', nextCounter);
setCounter((pre) => {
const nextCounter = pre + 1;
jsonLocalStorage.setItem('counter', nextCounter);
return nextCounter;
});
}
***
github : ‘repository’ / ( Git을 사용 )
배포- 원격 ‘저장소’
버전관리 = 형상관리
[git 설치] https://git-scm.com/download/win
주 사용 툴 선택
줄 읽는 방식(windows)
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/cpcpcool/app.git
git push -u origin main
- [최초생성 로컬기준 이메일/이름 입력 필요]
입력 후 로그인
생성 완료
세팅 후 배포완료
* array-ex01 배열함수
<h1>배열함수</h1>
<script>
const even = [2, 4, 6];
console.log(even);
// [요소(item) 추가] =================================
// 1) 맨 앞에 추가 .unshift();
even.unshift(0);
console.log(even);
even.unshift(-2, -4);
console.log(even);
// 2) 맨 뒤에 추가 .push();
even.push(8);
even.push(10, 12);
console.log(even);
// [요소(item) 삭제] =================================
// 1) 맨 앞에서 삭제 .shift();
const shift1 = even.shift();
console.log('shift1 >>', shift1);
console.log('even', even);
// 2) 맨 뒤에서 삭제 .pop();
const pop = even.pop();
console.log('pop >>', pop);
console.log('even', even);
// [요소(item) 추출] =================================
// [문법] 배열.slice(시작인덱스, 끝인덱스)
// 시작인덱스 포함, 끝인덱스 미포함
const slice1 = even.slice(1, 3); // 인덱스 1, 2
console.log('slice1 >>', slice1);
const slice2 = even.slice(-2); // 인덱스 끝에서 2개
console.log('slice2 >>', slice2);
// [요소(item) 삭제 및 추가] =========================
// [문법] 배열.splice(시작인덱스, 삭제개수);
// 시작인덱스로부터 ~ 개 삭제
even.splice(1, 2);
console.log(even);
// [문법] 배열.splice(시작인덱스, 삭제개수, 추가요소(기준위치에서 왼쪽));
even.splice(-2, 0, 20, 30) //
console.log(even);
// [요소(item) 추가] =================================
// [문법] 배열.concat(요소, 배열, ...) 뒤로 추가
const odd = [1, 3, 5];
concat1 = odd.concat(7, 9);
console.log('concat1 >>', concat1);
concat2 = odd.concat([11, 13]); // 배열째로여도 요소형태로 추가
console.log('concat1 >>', concat2);
</script>
* array-ex02 배열함수
<script>
// [배열의 특정 요소 찾기(탐색)] =================================
// [문법]
// 배열.indexOf(요소, 시작인덱스)
// : 시작인덱스에서 부터 시작해서 요소 탐색
// : 시작인덱스를 생략하면, '인덱스 0'부터 탐색
// : 있으면 해당요소의 인덱스 리턴, 없으면 -1 리턴
//
// 배열.lastIndexOf(요소, 시작인덱스) // 오른쪽 부터
// : 시작 인덱스부터 요소 탐색
// : 시작 인덱스를 생략하면, '끝'에서 부터 탐색
// : 있으면 해당요소의 인덱스 리턴, 없으면 -1 리턴
//
// 배열.includes(요소, 시작인덱스) // 시작인덱스 생략가능
// : 시작인덱스에서 부터 요소 탐색
// : 있으면 true 리턴, 없으면 false 리턴
const arr = [1, 10, false, NaN, null, 10];
console.log('[있는 요소] 10 찾아라!');
console.log('indexOf : ', arr.indexOf(10)); // 1
console.log('indexOf : ', arr.lastIndexOf(10)); // 5
console.log('indexOf : ', arr.includes(10)); // true
console.log('[없는 요소] 9 찾아라!');
console.log('indexOf : ', arr.indexOf(9)); // -1
console.log('indexOf : ', arr.lastIndexOf(9)); // -1
console.log('indexOf : ', arr.includes(9)); // false
console.log('[있는 요소] false 찾아라!'); // 논리값: 모두 가능
console.log('indexOf : ', arr.indexOf(false)); // 2
console.log('indexOf : ', arr.lastIndexOf(false)); // 2
console.log('indexOf : ', arr.includes(false)); // true
console.log('[있는 요소] NaN 찾아라!'); // NaN: index못찾음/ includes구분가능
console.log('indexOf : ', arr.indexOf(NaN)); // -1
console.log('indexOf : ', arr.lastIndexOf(NaN)); // -1
console.log('indexOf : ', arr.includes(NaN)); // true
console.log('[있는 요소] null 찾아라!'); // null: 모두 가능
console.log('indexOf : ', arr.indexOf(null)); // 4
console.log('indexOf : ', arr.lastIndexOf(null)); // 4
console.log('indexOf : ', arr.includes(null)); // true
</script>
** [find]와 [filter]
// [find] ================================================
// [문법] 배열.find(function(value, index, array))
// : 조건에 맞는 요소 1개만 찾음
// : 즉, 조건에 맞는 요소를 찾으면 탐색 중지
// : 있으면 해당요소를 리턴, 없으면 undefined 리턴
//
// [filter] ================================================
// [문법] 배열.filter(function(value, index, array))
// : 조건에 맞는 요소를 모두 찾음
// : 조건에 맞는 요소를 찾으면 배열로 리턴
// [find] ==========================================================
// [문법] 배열.find(function(value, index, array))
// : 조건에 맞는 요소 1개만 찾음
// : 즉, 조건에 맞는 요소를 찾으면 탐색 중지
// : 있으면 해당요소를 리턴, 없으면 undefined 리턴
const num = [3, 4, 5, 6, 7, 8, 9, 10];
const find_result = num.find(value => value % 2 == 0)
console.log('find_result >> ', find_result); // 4
// 4를 찾고 리턴(바로 중단) / 없으면 undefined
// [filter] ========================================================
// [문법] 배열.filter(function(value, index, array))
// : 조건에 맞는 요소를 모두 찾음
// : 조건에 맞는 요소를 찾으면 배열로 리턴
const filter_result = num.filter(value => value % 2 == 0)
console.log('filter_result >> ', filter_result); // [4, 6, 8, 10]
// 배열 형태로 전부리턴 / 없으면 [] 빈배열
* array-ex03 배열함수
[배열을 순회하면서 특정 작업]
<script>
// [배열을 순회하면서 특정 작업]
// [map] =================================================
// [문법] 배열.map(function(value, index, array))
// : 배열 리턴
const num = [3, 4, 5, 6, 7, 8];
const map_result = num.map(value => value * 2);
console.log('map_result >> ', map_result); // [6, 8, 10, 12, 14, 16]
// [forEach] =============================================
// [문법] 배열.forEach(function(value, index, array))
// : 리턴 없음
const forEach_result = num.forEach(value => value * 2);
console.log('forEach_result >> ', forEach_result); // return 없음
console.log('num >> ', num); // [3, 4, 5, 6, 7, 8]
const forEach_result2 = num.forEach(value => {
const result = value * 2
console.log(result); // 6, 8, 10, 12, 14, 16 (배열 X)
});
</script>
** [module] : (index.html, index.js, item.js)
보통 배포 시 컴포넌트 파일을 따로 만들고 분리시켜
가져다쓰는 형태를 많이 사용한다.
<모듈 구성>
: 하나의 모듈/파일 안에는 하나의 기능이 있는게 이상적
(관련있는 기능들까진 괜찮다)
index.html
<body>
<h1>모듈</h1>
<script src="index.js" type="module"></script>
</body>
type=“module” 필요
index.js
// 모듈 읽어오기(가져오기)
console.log('index.js 실행됨!');
// [1. named exports : 이름이 정의된 내보내기] ==============
// [문법]
// import {이름} from '파일 경로/파일명.확장자';
// 1.1) 방법 1
import { info } from './item.js'; // ./ 현재위치로 시작해야함
info();
// 1.2) 방법 2
import { edit, del } from './item.js';
edit();
del();
// 한 번에 가져오기
// as : alias(별칭)
import * as obj from './item.js';
// 별칭의 property 속성으로 접근
obj.info();
obj.edit();
obj.del();
// [2. default exports : 기본 내보내기 ======================
// [문법]
// {} 생략 필요, 이름변경 가능
// import 이름 from '파일경로/파일명.확장자';
import add from './item.js';
add();
// 어차피 한 모듈내에 하나만 하므로 이름달라도 되지만,
// 보통 이름은 통일해준다.
import Add from './item.js';
Add();
item.js
// [내보내기] ****************************
// export 키워드 사용
// ***************************************
console.log('item.js 파일입니다.')
// export / import 연결만으로도 실행됨
// 1. named exports ================================
// : 이름이 정의된 내보내기 방식
// : 함수, 변수 등 왼쪽에 export키워드 사용 // *
// : 한 모듈 내 여러 개 내보내기 가능
// =================================================
// 1.1) 방법 1 : export 키워드를 함수명 왼쪽에 바로 사용
export function info() { // *
console.log('등록된 상품이 없습니다.');
}
// 1.2) 방법 2 : export 키워드를 별도로 사용
function edit() {
console.log('상품 수정합니다.');
}
function del() {
console.log('상품 삭제합니다.');
}
// 여러 개 한번에 내보내기
export { edit, del };
// [2. default exports] ================================
// : 기본 내보내기 방식
// : 한 모듈 내 단 1개만 default 지정 가능
// =====================================================
// 2.1) 방법 1 : default 키워드를 함수에 바로 사용
// export default function add() {
// console.log('상품이 등록되었습니다');
// }
// 2.2) 방법 2 : default 키워드를 별도로 사용
function add() {
console.log('상품이 등록되었습니다');
}
export default add; // 가장 많이쓰는 형태