CreateSlice : reducer를 만드는 것을 도와주는 역할. CreateSlice는name,initialState,reducers3개를 반환 name: CreateSlice의 이름. 유일한 키값을 자동으로 생성해준다. initialState : 초기값 설정 reducers: 사용될 기능들을 담는 곳. 내부 객체에서 함수로 변환하여 만들게 됨.
기존의 redux의 리듀서에서는 전개연산자(…state)를 사용하여 기존의 리스트들을 넣으면서 바꿀 대상을 변경하여 return 해주는 방식으로 사용했었다. 하지만 redux-toolkit에서는 반복해왔던 return과 …state를 생략할 수 있으며 수정된 데이터만 설정해주면 redux-toolkit이 자동으로 값을 넣어주게 된다. 또한 컴포넌트에서 dispatch할때 리듀서에서 export한 action creator의 값을 들고와서 사용한다.
console.log(counterSlice)
Store
redux가 버전 업데이트를 하면서 기존의 createStore를 권장하지 않음. CombineReducer을 사용하지 않게 됨
이제는 새로운 configureStore()을 권장.
import { configureStore } from "@reduxjs/toolkit";
import counter from "../modules/counterSlice";
const store = configureStore({
reducer: { counter: counter },
});
Dispatch
redux-toolkit은 리듀서에 있는 함수를 어떻게 불러 올 수 있을까?
기존 redux
dispatch({type:”ADD_TODO”, payload:{data}})
Redux-toolkit
dispatch(addNumber.getSingleProduct(number))
Action creator의 내부 메서드에 인자 값으로 데이터(변수)를 넣게되면 자동으로 payload의 값으로 들어가게 된다.
Axios를 사용할 때에는 어떤 상황에서 path variable을 사용할지 query를 사용할지는 API 명세서를 보고 판단해야 한다.
path variable = /posts/1
query = /posts?title=json-server&author=typicode
POST
// POST 요청 전송
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
//편의를 위해 지원하는 메소드의 명령어
const onSubmitHandler = (data) => {
axios.post("/user/12345", data); //axios.post(url[, data[, config]])
};
새로운 리소스를 생성할 때 사용하는 메서드.
post 메서드의 두 번째 인자는 본문으로 보낼 데이터를 설정한 객체 리터럴을 전달한다.
여러 개의 요청을 동시 수행할 경우,axios.all()메서드를 사용
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// Both requests are now complete
}));
PATCH,PUT
어떤 데이터를 수정하고자 서버에 요청을 보낼때 사용하는 메서드.
PUT은리소스의 모든 데이터를 수정한다.
PATCH는요청하는 부분만 업데이트를 진행한다.
API명세서를 작성할때 PUT이나 PATCH 같은 용어들은 수정을하거나 삭제를 할때, 용어들을 다르게 자유자재로 써도 상관없지만 HTTP에서 정해진 규칙을 만들어 개발자들 상호간에 약속을 해놓고 사용하는 편이다.
React.createContext()로 생성한 Context 객체를 원하는 클래스의 contextType 프로퍼티로 지정할 수 있다. 이 프로퍼티를 활용해 클래스 안에서 this.context를 이용해 해당 Context의 가장 가까운 Provider를 찾아 그 값을 읽을 수 있게 된다.
※ 주의 - API를 사용하면 하나의 context만 구독할 수 있다
Context.Consumer
<MyContext.Consumer>
{value => /* context 값을 이용한 렌더링 */}
</MyContext.Consumer>
context 변화를 구독하는 React 컴포넌트 컴포넌트를 리턴할 수 있는 함수를 자식으로 두면서 값을 그대로 사용해서 렌더할 수 있게해준다. Context.Consumer의 자식은 함수여야 한다.
Profiler는 React 트리 내에 어디에나 추가될 수 있으며 트리의 특정 부분의 렌더링 비용을 계산해준다. 이는 두 가지 props를 요구하는데, id (문자열) 와 onRender 콜백 (함수)이며 React 트리 내 컴포넌트에 업데이트가 “커밋”되면 호출한다. 자식들 중에 이미 그려졌던 애들은 반복해서 사용하기 때문에 비효율을 줄일 수 있다.
이 함수는 무엇이 렌더링 되었는지 그리고 얼마나 걸렸는지 설명하는 입력값을 받게 됨
function onRenderCallback(
id, // 방금 커밋된 Profiler 트리의 "id"
phase, // "mount" (트리가 방금 마운트가 된 경우) 혹은 "update"(트리가 리렌더링된 경우)
actualDuration, // 커밋된 업데이트를 렌더링하는데 걸린 시간
baseDuration, // 메모이제이션 없이 하위 트리 전체를 렌더링하는데 걸리는 예상시간
startTime, // React가 언제 해당 업데이트를 렌더링하기 시작했는지
commitTime, // React가 해당 업데이트를 언제 커밋했는지
interactions // 이 업데이트에 해당하는 상호작용들의 집합
) {
// 렌더링 타이밍을 집합하거나 로그...
console.log(`actualDuration(${title}:${actualDuration})`);
}
※ 주의사항 Profiler는 가벼운 컴포넌트이지만 조금의 CPU와 메모리 비용을 추가하게 되기 때문에 필요할 때만 사용해야 한다.
memo함수를 사용하지 않은 화면memo함수 사용한 화면
useCallback
useCallback함수는 메모이제이션된 콜백을 반환한다. 특정 함수를 새로 만들지 않고 재사용하고 싶을때 사용한다.
현재 Comments 에서는 handleChange라는 함수를 새로 만들어서 자식 컴포넌트인 CommentItem에 전해주고 있다. 그렇다면 props로 전달해주는 새로운 함수를 리렌더링해줘야 하기때문에 memo는 사용할 수 가 없게 된다.
map함수 사용하여 props를Item 컴포넌트로 반환하고 TodoList에 저장한 후 return 한다.
Key
리액트는 페이지 전부를 렌더링하는 것이 아니라 기존과 비교하여 수정되는 부분만 렌더링해주는 방식이다.
이 과정에서 고유한 Key값이 없다면 모든 데이터를 비교해야 하지만, Key가 있으면 Key값만 비교하여 Key가 추가 됐는지, 삭제 됐는지만 비교하면 돼서 불필요한 렌더링을 없애준다.
즉 ,Key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕는다.
key로 컴포넌트 추출하기
위 코드의 경우 Item컴포넌트를 추출하는 과정에서 key값은 Item컴포넌트에 넣어줬다. 그 이유는 엘리먼트가 map 함수로 인해 여러개 생성되는데, 뭉쳐있는 형제 엘리먼트 사이에서 서로 고유성을 가져야하기 때문에 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정하는 것.
또한 key는 어튜리뷰트(속성)이기 때문에 props로 전달 되는 것은 아니니 참고하면 좋을 듯하다.