주의 일부만 업데이트할 때 상태를 얼마나 깊이 복제해야 하는가?
최근까지 나는 항상 lodash의 복제품 Deep을 사용해 내 상태를 복사한 다음 값을 바꾸고 복제된 상태를 반환했다.예를 들어 다음과 같다.
이것이 나의 초기 상태일 것이다.
{
"id": 1213,
"title": "Some title...",
"pages": {
"page1": {
"id": 459,
"title": "Some Page title...",
"fields": {
"field_1": {
"title": "My field",
"type": "text",
"value": "my text value..."
},
"field_2": {
"title": "My field 2",
"type": "text",
"value": "my text two value..."
},
"field_3": {
"title": "My field 3",
"type": "text",
"value": "my text value..."
}
}
}
}
}
이제 field_2의 값을 업데이트하고 싶다.
내 환원기는 이렇게 보일 것이다.
import cloneDeep from 'lodash/fp/cloneDeep';
export default function reducer(state, action) {
const {type, payload} = action;
switch (type) {
case 'UPDATE_FIELD_VALUE': {
const { pageIdent, fieldIdent, newValue } = payload;
// This is what I'm doing right now....
const newState = cloneDeep(state);
newState.pages[pageIdent]fields[fieldIdent]value = newValue;
return newState;
// Instead could I do this?
return {
...state,
state.pages[pageIdent]fields[fieldIdent]value = newValue;
}
}
}
}
그래서 항상 딥 클론을 할 필요는 없다고 읽었는데...하지만 내가 읽은 다른 곳에서는 같은 물건을 돌려줄 수 없다고 했어. 항상 새로운 물건을 돌려줘야 해.그렇다면 이 일을 하는 올바른 방법은 무엇일까?
그래, 그러지 마.딥 클론 상태를 유지해야 하는지 여부에 대한 Redex FAQ 인용:
상태 업데이트란 일반적으로 딥 카피가 아닌 얄팍한 카피를 만드는 것을 의미한다.얕은 복사본은 깊은 복사본보다 훨씬 더 빠르다. 왜냐하면 적은 수의 개체와 필드를 복사해야 하기 때문이다. 그리고 그것은 효과적으로 몇몇 포인터를 움직이는 것으로 귀결된다.
그러나 영향을 받는 각 중첩 수준에 대해 복사 및 업데이트된 개체를 만들어야 한다.비록 그것이 특별히 비용이 많이 들지는 않지만, 그것은 당신이 가능한 한 정상화되고 얕게 당신의 상태를 유지해야 하는 또 다른 좋은 이유야.
일반적인 Redex 오해: 상태를 깊이 복제할 필요가 있다.현실: 내부의 무언가가 변하지 않는다면, 그 참조를 그대로 유지하라!
그래서, 당신은 "심층 클론"을 원하지 않고 "중요한 얕은 클론"을 필요로 한다.
딥 클로닝은 두 가지 면에서 성능에 좋지 않다. 즉, 모든 것을 복제하는 데 더 많은 작업이 필요하며, 새로운 개체 참조는 실제로 가치가 변경되지 않은 데이터에 대한 UI 업데이트를 유발한다(그러나 새로운 참조는 UI가 무언가 변경되었다고 생각하게 한다).
"불가능한 업데이트 패턴"의 Redex 문서 페이지를 읽으십시오.해당 페이지의 중첩 상태 업데이트 예:
function updateVeryNestedField(state, action) {
return {
....state,
first : {
...state.first,
second : {
...state.first.second,
[action.someId] : {
...state.first.second[action.someId],
fourth : action.someValue
}
}
}
}
}
만약 당신이 그것이 너무 지루하거나 고통스럽다면, 당신은 당신의 상태를 어떻게 구조화하는지를 바꾸어야 한다. 그렇지 않으면 당신은 업데이트 과정을 처리하기 위해 그곳에 있는 많은 불변의 업데이트 유틸리티 라이브러리들 중 하나를 사용할 수 있다.
항상 국가 개체의 복제 작업을 해서는 안 된다.Redex는 다음을 보장할 수 있는 경우 빛을 발한다.
- 주의 유일한 변경 부분은 환원기에 제공된 조치에 기초하여 변경해야 하는 부분이다.그러니까 업데이트하는 거면
field_1
, 에 관한 것은 없다.field_2
바뀌어야 한다. - 주(州)의 한 부분이 바뀌어야 한다면, 언제나 달라진다.따라서 작업이 업데이트되면
field_2
, 그리고 그 다음field_2
객체 참조가 변경되어야 한다.
만약 당신의 주에서 '심층' 업데이트를 허용한다면 이것은 훨씬 더 쉽다.상태 정상화는 환원 앱에서 사용되는 더 나은 '패턴' 중 하나이며 문서에 설명되어 있다.
예를 들어, 당신의 상태를 약간 재구성해 봅시다(최고 수준은book
개체 및 필드 ID는 전역적으로 고유함:
초기 상태
"books" : {
"1213": {
"id": 1213,
"title": "Some title...",
"pages: [..., "page1", ...],
}
},
"pages": {
"page1": {
"id": 459,
"title": "Some Page title...",
"fields": [..., "field_1", "field_2", "field_3", ...],
}
},
"fields": {
"field_1": {
"title": "My field",
"type": "text",
"value": "my text value..."
},
"field_2": {
"title": "My field",
"type": "text",
"value": "my text value..."
},
"field_3": {
"title": "My field",
"type": "text",
"value": "my text value..."
}
}
각 'book' 엔티티에는 전체 오브젝트가 중첩되지 않고 페이지 ID 목록이 있다는 점에 유의하십시오.마찬가지로 각 페이지에는 실제 필드가 아닌 필드 ID 목록이 있다.이렇게 하면 모든 데이터 전송 엔티티가 '최고 수준' 상태에 저장되고 전체 상태를 건드리지 않고도 독립적으로 업데이트할 수 있다.
당신의 상태 구조를 평평하게 함으로써, 당신은 당신의 상태의 작은 부분에만 관계되는 '하위 축소 장치'를 만들 수 있다.위와 같은 경우에는 다음과 같이 처리한다.
import { combineReducers } from 'redux';
// This reducer handles all actions that affect book entities
const books = (state = {}, action = {}) => state;
// This reducer handles all actions that affect page entities
const pages = (state = {}, action = {}) => state;
// This reducer handles all actions that affect field entities.
// For your problem, this would look like:
const fields = (state = initialFields, action = {}) => {
switch (action.type) {
case 'UPDATE_FIELD_VALUE':
return {
...state,
[fieldIdent]: {
...state[fieldIdent],
value: newValue,
}
}
default:
return state;
}
}
// This results in the state structure above
const reducer = combineReducers({
books,
pages,
fields,
});
위의 코드에서 필드의 변경은 페이지나 장부 엔티티에 영향을 미치지 않으므로 불필요한 재렌더를 방지한다.즉, field_2 값을 변경하면 field_2 객체가 변경되고 필요에 따라 다시 렌더링될 것이 분명하다.
JSON API 응답 데이터에서 이렇게 상태를 구성하는 데 도움이 되는 라이브러리가 있다.이것은 꽤 좋은 것이다: https://github.com/paularmstrong/normalizr
이것이 도움이 되기를!
나는 페이스북의 불변의 j가 너의 모든 문제를 해결한다고 생각해.여기서 문서 읽기
'Programing' 카테고리의 다른 글
Python - 'ascII' 코덱에서 바이트를 디코딩할 수 없음 (0) | 2022.03.17 |
---|---|
Python 3에서 Raw_input을 사용하는 방법 (0) | 2022.03.17 |
Windows에서 여러 Python 버전을 실행하는 방법 (0) | 2022.03.16 |
리액션 렌더 함수에서 빈 상태로 반환할 수 있는가? (0) | 2022.03.16 |
Python에서 '이넘'을 어떻게 대표할 수 있을까? (0) | 2022.03.16 |