React useState() 후크를 사용한 상태 개체 업데이트 및 병합
리액트 훅 문서 두 개가 좀 헷갈리네요상태 후크를 사용하여 상태 개체를 업데이트하기 위한 베스트 프랙티스는 무엇입니까?
가 다음 상태를 갱신한다고 가정합니다.
INITIAL_STATE = {
propA: true,
propB: true
}
stateAfter = {
propA: true,
propB: false // Changing this property
}
옵션 1
Using the React Hook 기사에서는 다음과 같은 내용이 가능합니다.
const [count, setCount] = useState(0);
setCount(count + 1);
그래서 내가 할 수 있는 일:
const [myState, setMyState] = useState(INITIAL_STATE);
그 후:
setMyState({
...myState,
propB: false
});
옵션 2
Hooks Reference에서는 다음과 같은 정보를 얻을 수 있습니다.
클래스 컴포넌트에 있는 setState 메서드와 달리 useState는 업데이트개체를 자동으로 Marge하지 않습니다.함수 업데이터 폼과 오브젝트 확산 구문을 조합하여 이 동작을 복제할 수 있습니다.
setState(prevState => {
// Object.assign would also work
return {...prevState, ...updatedValues};
});
제가 알기로는 둘 다 효과가 있어요.그럼, 차이점은 무엇일까요?어떤 것이 베스트 프랙티스입니까?이전 상태에 액세스하려면 pass 함수(OPTION 2)를 사용해야 합니까, 아니면 확산 구문(OPTION 1)을 사용하여 현재 상태에 액세스해야 합니까?
가지 '두 가지 선택지 모두'와 같이 사용할 수 있습니다.setState
클래스 컴포넌트에서는 이미 상태가 되어 있는 것부터 파생된 상태를 갱신할 때는 주의가 필요합니다.
예를 들어 카운트를 연속으로 두 번 업데이트하는 경우 상태 업데이트의 함수 버전을 사용하지 않으면 예상대로 작동하지 않습니다.
const { useState } = React;
function App() {
const [count, setCount] = useState(0);
function brokenIncrement() {
setCount(count + 1);
setCount(count + 1);
}
function increment() {
setCount(count => count + 1);
setCount(count => count + 1);
}
return (
<div>
<div>{count}</div>
<button onClick={brokenIncrement}>Broken increment</button>
<button onClick={increment}>Increment</button>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
useState() hooks update for object를 검색하는 사용자가 있는 경우
스루 입력
const [state, setState] = useState({ fName: "", lName: "" }); const handleChange = e => { const { name, value } = e.target; setState(prevState => ({ ...prevState, [name]: value })); }; <input value={state.fName} type="text" onChange={handleChange} name="fName" /> <input value={state.lName} type="text" onChange={handleChange} name="lName" />
onSubmit 또는 버튼 클릭을 통해
setState(prevState => ({ ...prevState, fName: 'your updated value here' }));
베스트 프랙티스는, 다른 콜을 사용하는 것입니다.
const [a, setA] = useState(true);
const [b, setB] = useState(true);
코드가 인 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "2"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 "1"의 ""의"의왜냐하면 이러한 코드는 종종 오래된 값을 가진 폐쇄 내에 있기 때문입니다.myState
.
옵션 2는 새 상태가 이전 상태에 기반할 때 사용해야 합니다.
setCount(count => count + 1);
복잡한 상태 구조의 경우 useReducer 사용을 검토하십시오.
일부 형태와 논리를 공유하는 복잡한 구조의 경우 사용자 지정 후크를 작성할 수 있습니다.
function useField(defaultValue) {
const [value, setValue] = useState(defaultValue);
const [dirty, setDirty] = useState(false);
const [touched, setTouched] = useState(false);
function handleChange(e) {
setValue(e.target.value);
setTouched(true);
}
return {
value, setValue,
dirty, setDirty,
touched, setTouched,
handleChange
}
}
function MyComponent() {
const username = useField('some username');
const email = useField('some@mail.com');
return <input name="username" value={username.value} onChange={username.handleChange}/>;
}
상태 후크를 사용하여 상태 개체를 업데이트하기 위한 베스트 프랙티스는 무엇입니까?
다른 답변이 지적한 바와 같이 둘 다 유효합니다.
차이점은 무엇입니까?
혼란은 이 때문에 생긴 것 같다."Unlike the setState method found in class components, useState does not automatically merge update objects"
★★★★★★★★★★★★★★★★★★★★★★★★★★★
비교해보죠.this.setState
&useState
class SetStateApp extends React.Component {
state = {
propA: true,
propB: true
};
toggle = e => {
const { name } = e.target;
this.setState(
prevState => ({
[name]: !prevState[name]
}),
() => console.log(`this.state`, this.state)
);
};
...
}
function HooksApp() {
const INITIAL_STATE = { propA: true, propB: true };
const [myState, setMyState] = React.useState(INITIAL_STATE);
const { propA, propB } = myState;
function toggle(e) {
const { name } = e.target;
setMyState({ [name]: !myState[name] });
}
...
}
다 하다 하다, 하다, 하다, 하다.propA/B
toggle
그리고 둘 다 하나의 만 업데이트한다.e.target.name
.
「 1 」에서 1개의 .setMyState
.
에서는 을 줍니다.propA
setMyState
삭제)
따라오셔도 됩니다.
경고:구성 요소가 제어된 유형의 입력 확인란을 제어되지 않도록 변경하고 있습니다.입력 요소는 제어에서 비제어(또는 그 반대)로 전환해서는 안 됩니다.컴포넌트의 라이프 타임 동안 제어된 입력 요소를 사용할지 또는 제어되지 않은 입력 요소를 사용할지 결정합니다.
냐하 on on on on를 propA
켜겠습니다.propB
되어 「」만 됩니다.propA
「」가 됩니다.propB
의 »checked
값이 정의되지 않음으로 지정되면 확인란이 제어되지 않습니다.
★★★★★★★★★★★★★★★★.this.setState
만, 「」는 「」입니다.merges
따라서 체크박스는 제어된 상태로 유지됩니다.
은 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★useState
, " "useReducer
intern적 intern intern internuseState
®useReducer
반환하는 모든
useState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
currentHookNameInDev = 'useState';
...
try {
return updateState(initialState);
} finally {
...
}
},
서 ''는updateState
의 내부 실장입니다.useReducer
.
function updateState<S>(
initialState: (() => S) | S,
): [S, Dispatch<BasicStateAction<S>>] {
return updateReducer(basicStateReducer, (initialState: any));
}
useReducer<S, I, A>(
reducer: (S, A) => S,
initialArg: I,
init?: I => S,
): [S, Dispatch<A>] {
currentHookNameInDev = 'useReducer';
updateHookTypesDev();
const prevDispatcher = ReactCurrentDispatcher.current;
ReactCurrentDispatcher.current = InvalidNestedHooksDispatcherOnUpdateInDEV;
try {
return updateReducer(reducer, initialArg, init);
} finally {
ReactCurrentDispatcher.current = prevDispatcher;
}
},
Redx에 익숙한 경우 일반적으로 옵션 1에서처럼 이전 상태로 확산하여 새 개체를 반환합니다.
setMyState({
...myState,
propB: false
});
따라서 하나의 속성만 설정하면 다른 속성은 병합되지 않습니다.
사용 사례에 따라 상태 유형에 대한 하나 이상의 옵션이 적합할 수 있습니다.
일반적으로 다음 규칙에 따라 원하는 상태를 결정할 수 있습니다.
첫 번째: 각각의 상태가 관련되어 있는가?
응용 프로그램에 있는 개별 상태가 서로 관련되어 있는 경우 개체 내에서 이들을 그룹화할 수 있습니다. 않으면 떼어놓고 개를 이 좋습니다.useState
특정 때는 핸들러에 는 신경 않습니다.
예를 들어 다음과 같은 사용자 속성name, email
할 수 또, 를 유지하는 는, 「」를 사용할 수 .multiple useState hooks
두 번째: 상태를 갱신하는 논리는 복잡하며 핸들러 또는 사용자의 조작에 따라 달라집니다.
위와 같은 경우에는 다음을 활용하는 것이 좋습니다.useReducer
상태를 정의합니다.는 예를 , 여러분이 때 .update
,create
그리고.delete
서로 다른 상호작용에 있는 요소
이전 상태에 액세스하려면 pass 함수(OPTION 2)를 사용해야 합니까, 아니면 확산 구문(OPTION 1)을 사용하여 현재 상태에 액세스해야 합니까?
훅을 사용한 상태 업데이트도 일괄 처리되므로 이전 상태를 기반으로 업데이트하려면 콜백 패턴을 사용하는 것이 좋습니다.
업데이트 상태로의 콜백 패턴은, 세터가 1 회만 정의되어 있기 때문에, 폐쇄 폐쇄로부터 갱신된 값을 수신하지 않는 경우에도 편리합니다.예를 들어 다음과 같습니다.useEffect
이벤트 상태를 업데이트하는 수신기를 추가할 때 초기 렌더링 시에만 호출됩니다.
그 사용 예에서는 둘 다 문제 없습니다.전달되는 함수 인수setState
로 해 유효합니다(즉, 콜을 할 수 ).setState
다만, 기능상에서는 보다 깔끔하게 보입니다).또는, 이전 상태의 최신 버전에 즉시 액세스 할 수 없는 클로저로 상태를 설정했을 경우.
어떤 이유로든 윈도우에 마운트되어 한 번만 바인딩되는 이벤트청취자와 같은 예를 들 수 있습니다.예.
useEffect(function() {
window.addEventListener("click", handleClick)
}, [])
function handleClick() {
setState(prevState => ({...prevState, new: true }))
}
ifhandleClick
1을 이므로, 「1」로 됩니다.setState({...prevState, new: true })
이렇게 할 수 . 왜냐하면, 이 버그가, 이 버그가, 이 버그가, 이 버그가, 이 버그가, 라고 하는 것입니다prevState
는 초기 렌더링 시 상태만 캡처하고 업데이트에서는 캡처하지 않습니다.되었습니다.setState
는 항상 최신 상태 반복에 액세스할 수 있습니다.
두 옵션 모두 유효하지만 차이가 있습니다.옵션 1(setCount(카운트+1)을 사용하는 경우
- 브라우저 업데이트 시 속성은 시각적으로 중요하지 않습니다.
- 성능 향상을 위해 리프레시 레이트 희생
- 이벤트(event.target.value)에 따라 입력 상태를 갱신합니다.옵션 2를 사용하는 경우 event.persist()가 없는 한 퍼포먼스상의 이유로 이벤트가 늘로 설정됩니다.이벤트 풀링을 참조해 주세요.
옵션 2(setCount(c => c + 1)를 사용합니다.
- 브라우저에서 업데이트할 때 속성이 중요함
- 퍼포먼스를 희생하여 리프레쉬 레이트 향상
자동 손실 기능이 있는 알림이 일괄적으로 닫힐 때 이 문제가 발견되었습니다.
참고: 성능의 차이를 입증하는 통계는 없지만 React 16 성능 최적화에 대한 React 컨퍼런스를 기반으로 합니다.
i i i i i고 。useReducer
스테이트를 하기 위한 으로, 「」이 아닌 「 스테이트를 관리할 수 .useState
상태 및 업데이트 기능을 다음과 같이 초기화합니다.
const initialState = { name: "Bob", occupation: "builder" };
const [state, updateState] = useReducer(
(state, updates) => {...state, ...updates},
initialState
);
그런 다음 부분 업데이트만 전달하여 상태를 업데이트할 수 있습니다.
updateState({ occupation: "postman" })
제가 제안하는 솔루션은 위의 솔루션보다 훨씬 간단하고 망치지 않기 쉬우며 API와 동일한 사용법을 가지고 있습니다.
npm 패키지(여기)를 사용합니다.의존관계에 추가한 후 다음과 같이 사용합니다.
const useMergeState = require("use-merge-state") // Import
const [state, setState] = useMergeState(initial_state, {merge: true}) // Declare
setState(new_state) // Just like you set a new state with 'useState'
이게 모두에게 도움이 되길 바랍니다.:)
언급URL : https://stackoverflow.com/questions/55342406/updating-and-merging-state-object-using-react-usestate-hook
'source' 카테고리의 다른 글
Boost 속성 트리를 사용하여 어레이 읽기 (0) | 2023.02.22 |
---|---|
@JsonProperty 필드 및 getter/setter의 주석 (0) | 2023.02.18 |
python에서 json 문자열을 개체로 역직렬화합니다. (0) | 2023.02.16 |
Postgre 저장 방법Spring Boot + JPA를 사용한SQL jsonb? (0) | 2023.02.16 |
MongoDB GUI 클라이언트(크로스 플랫폼 또는 Linux) (0) | 2023.02.16 |