개인적인 스터디 용도로 작성 중이며,
빠른 시일 내로 업데이트할 예정입니다.
1. 시작하기 전, 개발환경 셋팅
2. 리액트의 생명주기 ( Life Cycle )
3. 리액트 + 리덕스
4. 리액트 훅
// eslint설정 파일인 .eslintrc 생성
{
"parser": "babel-eslint",
"env": {
"browser": true,
"es6": true,
"commonjs": true
},
"globals": {
"process": true
},
"extends": ["airbnb"],
"parserOptions": {
"ecmaVersion": 6,
"ecmaFeatures": {
"jsx": true
},
"sourceType": "module"
},
"plugins": ["react", "jsx-a11y", "import"],
"rules": {
"jsx-a11y/anchor-is-valid": [
"error",
{
"components": ["Link"],
"specialLink": ["hrefLeft", "hrefRight"],
"aspects": ["invalidHref", "preferButton"]
}
],
"linebreak-style": 0,
"react/prefer-stateless-function": 0,
"react/jsx-filename-extension": 0,
"react/jsx-one-expression-per-line": 0,
"react/prop-types": 0,
"react/jsx-uses-vars": [2],
"react/jsx-no-undef": "error",
"no-console": 0
}
}
4-2. Prettier
// prettier 설정파일인 .prettierrc 생성
{
"singleQuote": true,
"semi": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
참조
https://reactjs.org/docs/react-component.html
http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
이하, 리액트 공식문서의 내용을 아주 짧게 요약하였으며
위 링크에 접속하여 직접 읽어볼 것을 권장합니다.
// 생성자. 여기에서 선언할 state는 props로 내려받는 값 보다는, default로 정의할 값을 설정하는게 좋다.
constructor(props) {
super(props);
this.state = {
count: 0,
productList: [],
showPopup: false,
}
}
// 1. 데이터 호출해야 하는 경우
// 2. 화면이 한 번 그려지고나서 호출되기에, 크기나 위치에 따라 DOM Node를 체크해야 하는 경우
componentDidMount() {
this.getDataList();
}
getDataList = async() => {
await axios.get('https://blahblah.com/');
}
// 이전의 값과 지금의 값을 비교하여 무언가를 실행해야 할 경우
// ( ex. 상품A의 상세페이지에서 상품B의 상세페이지로 이동할 경우,
// 상품 id값의 변동을 확인하여 id값으로 상세페이지에 노출할 데이터만 갱신해줌으로써 화면의 일부를 새로 그린다. )
// [ Warrning ] : 잘못 사용할 경우, 무한루프가 발생하므로 유의할 것!!
componentDidUpdate(prevProps) {
if(this.props.productId !== prevProps.productId) {
this.getProductItem(prevProps.productId);
}
}
// 컴포넌트가 삭제되기 바로 직전에 실행되며, clearTimeout 등의 이벤트 제거에 사용된다.
componentWillUnMount() {
clearTimeout(foobar);
}
// 이전의 값과 지금의 값을 비교하여 특정조건에 따라 랜더링을 막을 수 있다.
// ( ex. 검색페이지에서 검색버튼을 누르기 전에 검색 필터가 바뀌더라도 랜더링을 다시 안할 수 있다. )
shouldComponentUpdate(nextProps, nextState) {
if(nextProps.item === nextState.item){
return false;
}
return true;
}
// props에서 받아온 값을 state에 동기화시킬 경우
// ( ex. 헤더 컴포넌트에 로그인 정보가 props로 받아질 경우, state에 저장 및 닉네임 노출 )
getDerivedStateFromProps(props, state) {
if(props.value !== state.value){
return {
user: props.value,
};
}
return null;
}
// 여기서 반환된 값은 componentDidUpdate의 3번째 인자인 snapshot으로 전달됩니다.
// 주로 스크롤 위치를 가져올 때 사용
getSnapShotBeforeUpdate(prevProps, prevState) {
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
Action이란, Store에 정보를 전달하기 위한 데이터 묶음으로
이벤트를 구분할 수 있는 식별자와 해당 이벤트의 실행에 필요한 값을 함께 가지고 있는 객체입니다.
{
type: "식별자",
payload: "값"
}
Action Creator란, Action을 생성해주는 함수이며 그게 전부입니다.
function AddTodo(){
return {
type: "식별자",
payload: "값"
}
}
Dispatch란, Component와 Store를 감시하며 값을 전달하는 역할을 합니다.
Component에서 Action이 발행되면, 감시하고 있던 Dispatch가 Action을 Reducer로 전달합니다.
Store에서 값이 변경되면, 감시하고 있던 Dispatch가 new State를 Component로 전달합니다.
Reducer란, 각 Action에 맞추어 어떻게 상태를 변화시킬지 관리하는 함수입니다.
Dispatch를 통해 전달된 Action과 기존 Store에 저장된 old State 객체를 합쳐서 new State 객체를 생성합니다.
이 때, 생성된 new State 객체는 Store에 저장됩니다.
Store란, 이 앱의 전체 상태를 저장하고 있는 저장소입니다.