리듀서에서 저장소가 변경되면 useSelector가 업데이트되지 않습니다.React JS 리덕스
나는 환원기로 상태를 바꾸고 있다.디버깅 시 상태가 실제로 변경되었음을 확인하였습니다.하지만 컴포넌트가 업데이트되지 않습니다.
컴포넌트:
function Cliente(props) {
const dispatch = useDispatch()
const cliente = useSelector(({ erpCliente }) => erpCliente.cliente)
const { form, handleChange, setForm } = useForm(null)
...
function searchCepChangeFields() {
//This call the action and change the store on reducer
dispatch(Actions.searchCep(form.Cep))
.then(() => {
// This function is only taking values from the old state.
// The useSelector hook is not updating with store
setForm(form => _.setIn({...form}, 'Endereco', cliente.data.Endereco))
setForm(form => _.setIn({...form}, 'Uf', cliente.data.Uf))
setForm(form => _.setIn({...form}, 'Cidade', cliente.data.Cidade))
setForm(form => _.setIn({...form}, 'Bairro', cliente.data.Bairro))
})
}
리듀서:
case Actions.SEARCH_CEP:
{
return {
...state,
data: {
...state.data,
Endereco: action.payload.logradouro,
Bairro: action.payload.bairro,
UF: action.payload.uf,
Cidade: action.payload.cidade
}
};
}
주의: redux-toolkit을 사용하여 코드 참조를 방지하는 것이 좋습니다.redux를 사용하기 위해서는 더 좋고 거의 필수적인 방법입니다.
여러분이 마주하는 문제는 물체를 다룰 때 매우 흔하고, 여러분이 물체의 속성을 바꾸고 있기 때문에 소품은 변하지 않지만, 물체 자체는 반응 측에서 변하지 않습니다.
참조가 그대로 유지되기 때문에 완전히 새로운 오브젝트 반응에서도 속성 오브젝트가 변경되지 않습니다.
다음과 같이 새 참조를 작성해야 합니다.
Object.assign(state.data,data);
return {
...state,
data: {
...state.data,
Endereco: action.payload.logradouro,
Bairro: action.payload.bairro,
UF: action.payload.uf,
Cidade: action.payload.cidade
}
}
이 문제를 해결하는 Immer 라이브러리에 대해 자세히 알아보십시오.
할 필요는 없다
Object.assign(state.data, data);
어레이 또는 객체의 데이터를 변경할 때 항상 사용 가능
return(
object: {...state.object, a: 1, b: 2},
array: [...state.array, 1, 2, 3]
)
이 3개의 점(...)는 반드시 새로운 오브젝트를 만듭니다.redex에서는 상태를 갱신할 뿐만 아니라 항상 새 개체를 생성해야 합니다.이렇게 하면 redux는 데이터가 변경되었음을 확인할 수 없습니다.
오브젝트 또는 어레이를 네스트하는 경우에도 마찬가지입니다.
다음 사항에 주의해 주십시오.
initialState = {
object: {
...object,
anotherObject:{
...anotherObject,
a: 1,
b: 2
}
}
}
어떤 이유에서인지 Object.assgin은 ES6 구문을 사용한 업데이트를 인식하지 않습니다.
updatedConnectors = state.connectors
그러면 현재 상태에 대한 참조가 생성됩니다.ES6에서는 ...을 도입하여 새로운 기준을 만듭니다.
updatedConnectors = { ...state.connectors }
.....
return {
...state,
connectors: updatedConnectors
};
이를 사용하여 새 참조를 추출하고 복사합니다.그것 또한 상태 변화를 유발합니다.
업데이트 9월 27일/20일 이 문제를 처리하기 위해 몇 가지 유틸리티 함수를 작성했습니다.해봅시다.
//Utils
export const getStateSection = ({ state, sectionName }) => {
const updatedState = { ...state }
const updatedSection = updatedState[sectionName]
return updatedSection
}
export const mergeUpdatedSection = ({ state, sectionName, updatedValue }) => {
const updatedState = { ...state }
updatedState[sectionName] = updatedValue
return updatedState
}
그런 다음 모든 환원제에서 다음과 같이 사용해야 합니다.
//reducer
const initState = {
scheduleDetail: null,
timeSlots: null,
planDetail: {
timeSlots: [],
modifedTimeSlots: [],
id: 0
}
}
.....
const handlePickTimeSlot = (state, action) => {
let planDetail = getStateSection({ state, sectionName: 'planDetail' })
// do stuff update section
return mergeUpdatedSection({ state, sectionName: 'planDetail', updatedValue: planDetail })
}
정교한 BA 편집 큐가 꽉 차서.
여기서 받아들여지는 대답은 데이터가 거기에 있다는 것이 그가 의미한 것이다.
case MYCASE:
let newDataObject = Object.assign(state.data, {...action.payload});
// or
// let newDataObject = Object.assign(state.data, {key: 'value', 'key2': 'value2' ...otherPropertiesObject);
return {
...state,
...newDataObject
}
스토어를 작성하는 파일을 수정할 때 발생할 수 있는 흥미로운 엣지 케이스가 있습니다.
레독스 스토어가 있는 파일이Provider컴포넌트(일반적으로 App.tsx)는 React의 핫 모듈 새로고침(HMR)에 의해 새로고침되지 않지만 리덕스 스토어 파일이 변경되어 HMR에 의해 새로고침되고 새로운 스토어가 생성되어 스토어가 생성됩니다.Provider는 실제로 redux 스토어의 오래된 인스턴스를 에 전달할 수 있습니다.
글에 과 같은 .setup-store.ts 삭제:
/**
* Note! When making changes to this file in development, perform a hard refresh. This is because
* when changes to this file are made, the react hot module reloading will re-run this file, as
* expected. But, this causes the store object to be re-initialized. HMR only reloads files that
* have changed, so the Store Provider in App.tsx *will not* be reloaded. That means useSelector
* values will be querying THE WRONG STORE.
*/
문제가 아닙니다. 리액트가 어떻게 작동하는지 이해해야 합니다.예상되는 동작입니다.
이 경우 호출하고 있습니다.
dispatch(dispatch(「」) searchCep(이하 「)」)를 참조해 주세요. Cep)
( ( ) { .. } 、 = > { ...★★★★★★★★★★★★...}
그러나 이 모든 작업은 하나의 렌더링에서 수행되며 변경된 저장소는 다음 렌더링에서만 수행됩니다. ★★★★★★★★★★★★★★★.then값이 업데이트된 다음 렌더에서가 아니라 첫 번째 렌더에서 소품을 가져옵니다.예를 들어 다음과 같습니다.
import React from 'react';
import { useSelector, useDispatch } from "react-redux";
import { selectCount, incrementAsync } from "./redux";
import "./styles.css";
export default function App() {
const value = useSelector(selectCount);
const dispatch = useDispatch();
const incrementThen = () => {
console.log("value before dispatch", value);
dispatch(incrementAsync(1)).then(() =>
console.log("value inside then", value)
);
};
console.log("render: value", value);
return (
<div className="App">
<p>{value}</p>
<button onClick={incrementThen}>incrementThen</button>
</div>
);
}
출력
value before dispatch 9
render: value 10
value inside then 9
언급URL : https://stackoverflow.com/questions/58850699/useselector-not-updating-when-store-has-changed-in-reducer-reactjs-redux
'programing' 카테고리의 다른 글
| 각진 문자열 분할 방법JS (0) | 2023.03.28 |
|---|---|
| jQuery.ajax 및 JSONP를 사용하여 헤더를 설정하시겠습니까? (0) | 2023.03.28 |
| Jest에서 onChange 함수 테스트 (0) | 2023.03.28 |
| configuration.loaders에 알 수 없는 속성 '로더'가 있습니다. (0) | 2023.03.23 |
| 리액트 파이버와 리액트 파이버의 차이점은 무엇입니까? (0) | 2023.03.23 |