☝🏻 컴포넌트를 쪼개는 방법은 사람마다 방식이 달라 내가 편한 쪽으로 쪼개면 OK!
단, 너무 작게 쪼개면 만들기 힘들고, 너무 크게 쪼개면 재활용이 힘들다.
☝🏻 defaultProps : 페이지를 그리는데 꼭 필요한 데이터를 담아두면 데이터가 없어서 나는 오류를 방지할 수 있다. (음,, initialState의 느낌?)
Post.defaultProps = { user_info: { user_name: 'fall_of_jul', user_profile: profile, }, img_url: profile, contents: '귀여운 김가을!', comment_cnt: 10, insert_dt: '2021-07-05 10:44:00', }
☝🏻 안에 들어가는 형식은 비슷하나 각 최소 단위 컴포넌트별로 적용해야하는 css가 달라서 참고!
elements 깃허브
☝🏻 최소 단위 컴포넌트가 너무 많아지면 components에 import해야하는 부분이 많아져 코드가 복잡해진다!
따라서, index.js 파일을 생성하여 한 곳에 최소 단위 컴포넌트를 묶어주면 간단하게 사용할 수 있다.import Grid from "./Grid"; import Image from "./Image"; import Text from "./Text"; export {Grid, Image, Text}
☝🏻 콜백 헬은 왜 발생할까?
- 비동기 처리 시 실행 완료를 기다리지 않고 바로 다음 작업을 실행하기 때문에 순서대로 코드를 짠다고 해서 우리가 원하는 순서로 작업이 이루어지지 않는다.
- 비동기 처리 함수 내에서 처리 결과를 반환하는 걸로는 원하는 동작을 하지 않으니 콜백 함수를 사용해 원하는 동작을 하게 만든다. 하지만 이 콜백 함수 내에서 또 다른 비동기 작업이 필요할 경우 중첩이 생기며 또 콜백 헬이 발생한다..
자바스크립트는 싱글 쓰레드로 동작하는 언어(메인 쓰레드 + 콜스택)이며 비동기 작업을 동시에 할 수 있다.
☝🏻 어떻게 동시 실행을 할까?
-> 자바스크립트는 코어 엔진만 가지고 돌아가는게 아닌 실행환경(런타임)의 도움을 받아 동시 실행한다.
비동기 연산이 종료된 이후 결과를 알기 위해 사용하는 객체
프라미스를 쓰면 비동기 메서드를 동기 메서드처럼 값을 반환할 수 있다.
-> 비동기 처리 시점을 좀 더 명확하게 표현할 수 있다.
// 프라미스 객체를 만듭니다.
// 인자로는 (resolve, reject) => {} 이런 excutor 실행자(혹은 실행 함수라고 불러요.)를 받아요.
// 이 실행자는 비동기 작업이 끝나면 바로 두 가지 콜백 중 하나를 실행합니다.
// resolve: 작업이 성공한 경우 호출할 콜백
// reject: 작업이 실패한 경우 호출할 콜백
const promise = new Promise((resolve, reject) => {
if(...){
...
resolve("성공!");
}else{
...
reject("실패!");
}
});
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000);
});
// resolve
promise.then(result => {
console.log(result); // 완료!가 콘솔에 찍힐거예요.
}, error => {
console.log(error); // 실행되지 않습니다.
});
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("오류!")), 1000);
});
// reject
promise.then(result => {
console.log(result); // 실행되지 않습니다.
}, error => {
console.log(error); // Error: 오류!가 찍힐거예요.
});
// 프라미스를 하나 만들어 봅시다!
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("오류!"), 1000);
});
promise.catch((error) => {console.log(error};);
new Promise((resolve, reject) => {
setTimeout(() => resolve("promise 1"), 1000);
}).then((result) => { // 후속 처리 메서드 하나를 쓰고,
console.log(result); // promise 1
return "promise 2";
}).then((result) => { // 이렇게 연달아 then을 써서 이어주는 거예요.
console.log(result);
return "promise 3";
}).then(...);
// async는 function 앞에 써줍니다.
async function myFunc() {
return "프라미스를 반환해요!"; // 프라미스가 아닌 걸 반환해볼게요!
}
myFunc().then(result => {console.log(result)}); // 콘솔로 확인해봅시다!
async function myFunc(){
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000);
});
console.log(promise);
let result = await promise; // 여기서 기다리자!하고 신호를 줍니다.
console.log(promise);
console.log(result); // then(후처리 함수)를 쓰지 않았는데도, 1초 후에 완료!가 콘솔에 찍힐거예요.
}
☝🏻 JWT vs OAuth
- 로그인에 많이 쓰이는 두 인증 방식으로 비교하긴 조금 애매하다.
JWT는 토큰의 한 형식이고 OAuth는 프레임워크이기 때문
(OAuth에서 토큰으로 JWT 사용 가능)
// key는 MY_COOKIE, value는 here,
document.cookie = "MY_COOKIE=here;";
console.log(document.cookie);
document.cookie = "MY_COOKIE=here; expires=new Date('2020-12-12').toUTCString()";
// key는 MY_SESSION, value는 here인 세션을 만들어요.
sessionStorage.setItem("MY_SESSION", "here");
// key값으로 쉽게 가져올 수 있어요 :)
sessionStorage.getItem("MY_SESSION");
// 하나만 삭제하고 싶다면, 이렇게 키를 통해 삭제합니다.
sessionStorage.removeItem("MY_SESSION");
// 몽땅 지우고 싶을 땐 clear()를 쓰면 됩니다. :)
sessionStorage.clear();
// key는 MY_LOCAL, value는 here인 데이터를 저장해요.
localStorage.setItem("MY_LOCAL", "here");
// key값으로 쉽게 가져올 수 있어요 :)
localStorage.getItem("MY_LOCAL");
// 하나만 삭제하고 싶다면, 이렇게 키를 통해 삭제합니다.
localStorage.removeItem("MY_LOCAL");
// 몽땅 지우고 싶을 땐 clear()를 쓰면 됩니다. :)
localStorage.clear();
☝🏻 프로젝트의 성향에 맞춰 저장 장소는 때마다 달라져야한다!
☝🏻 immer 패키지
- 객체는 const로 선언해도 내용이 수정될 수 있다.(기본 강의에서 정리함) 그래서 스프레드 문법({...})을 통해 수정되지 않게 작성한다. 하지만, 객체 구조가 복잡해지면 코드를 짜기가 번거로워 Immer가 불변성 관리를 대신 해줌으로써 불변성을 신경쓰지 않아도 됨!
//임포트 후 사용 import {produce] from 'immer';
- 첫번째 파라미터에는 수정하고 싶은상태, 두번째 파라미터에는 어떻게 업데이트 하고 싶은 지 정의하는 함수를 넣어줌
const state = { number: 1, dontChangeMe: 2 }; const nextState = produce(state, draft => { draft.number += 1; }); console.log(nextState); // { number: 2, dontChangeMe: 2 }
☝🏻 redex-actions 패키지
- 좀 더 편한 액션 관리를 위해 사용
(createAction, handleActions)//임포트 후 사용 import { createAction, handleActions } from "redux-actions";
const a = {b:2};
let a_value = a ? a.b : 0;
//= let a_value = a?.b;
import _ from "lodash"; // lodash 부르기
// shared/Search.js
import React from "react";
import _ from "lodash"; // lodash 부르기
const Search = () => {
const debounce = _.debounce((k) => console.log("디바운스! :::", k), 1000);
const keyPress = React.useCallback(debounce, []);
const onChange = (e) => {
keyPress(e.target.value);
};
return (
<div>
<label>Search:</label>
<input onChange={onChange} />
</div>
);
};
export default Search;
// shared/Search.js
import React from "react";
import _ from "lodash"; // lodash 부르기
const Search = () => {
const throttle = _.throttle((k) => console.log("쓰로틀! :::", k), 1000);
const keyPress = React.useCallback(throttle, []);
const onChange = (e) => {
keyPress(e.target.value);
};
return (
<div>
<label>Search:</label>
<input onChange={onChange} />
</div>
);
};
export default Search;
let query = postDB.orderBy("insert_dt", "desc").limit(2);
//desc > 내림차순 / 없으면 올림차순