无法在订阅体内的 setState 挂钩中调用先前状态的对象方法
Can't call object method on previous state in setState hook inside subscribe body
尝试使用 useState 钩子更新对象状态在 RxJS 主题订阅体内部不起作用,但在它外部起作用。 (在第二个代码部分用注释注释)
我收到的错误是:类型错误:eventMap.addEvent 不是函数
我的目标是使用来自 backpageMessageSubject$ 的事件从 EventMap 调用 addEvent,然后将返回的数组从 getNthEvent 方法传递给子组件。
class EventMap {
eventArrays;
constructor() {
this.eventArrays = new Map();
}
addEvent = (id, data) => {
this.eventArrays.has(id)
? this.eventArrays.get(id).push(data)
: this.eventArrays.set(id, [data]);
return this.eventArrays;
}
getNthEvent = (n) => {
const result = [];
for (let key of this.eventArrays.keys()) {
result.push(this.eventArrays.get(key)[n]);
}
return result;
}
}
export default function MarbleDiagram(props) {
const [eventMap, setEventMap] = useState(new EventMap());
// Stream of events for this observable.
const event$ = backpageMessageSubject$.pipe(
filter(message => message.type === 'event'),
map(message => message.event),
filter(event => event.observable === props.observable)
);
useEffect(() => {
const eventSubscription = event$.subscribe(event => {
setEventMap(eventMap => eventMap.addEvent(1, 1)); // This does trigger error.
});
setEventMap(eventMap => eventMap.addEvent(1, 1)); // This does not trigger error.
return () => {
eventSubscription.unsubscribe();
};
}, []);
}
主题来源:
export const backpageMessageSubject$ = new Subject();
完成 setEventMap(eventMap => eventMap.addEvent(1, 1))
后,事件地图的状态是 eventMap.addEvent
的 return 值 ,这不是 EventMap
实例。因此,稍后当您尝试使用它时,它会失败,因为您正在使用的 (Map
) 没有 addEvent
.
由于不能直接修改状态中的项目,您需要更新 EventMap
以便它 return 成为具有添加事件的地图的新实例,而不是改变现有的地图,沿着这些线:
class EventMap {
eventArrays;
constructor(eventArrays = new Map()) { // Note accepting a parameter
this.eventArrays = eventArrays;
}
addEvent = (id, data) => {
// Copy the current map, reusing the same arrays
const eventArrays = new Map(this.eventArrays);
// Get the current array for this `id`
const current = eventArrays.get(id);
if (!current) {
// We don't have it, create a new one in the new map
eventArrays.set(id, [data]);
} else {
// We have it, copy its contents to a new array and
// add the new data to the end, storing it in the
// new map
eventArrays.set(id, [...current, data]);
}
// Create a new EventMap with those arrays and return it
return new EventMap(eventArrays);
}
getNthEvent = (n) => {
const result = [];
for (let key of this.eventArrays.keys()) {
result.push(this.eventArrays.get(key)[n]);
}
return result;
}
}
尝试使用 useState 钩子更新对象状态在 RxJS 主题订阅体内部不起作用,但在它外部起作用。 (在第二个代码部分用注释注释)
我收到的错误是:类型错误:eventMap.addEvent 不是函数
我的目标是使用来自 backpageMessageSubject$ 的事件从 EventMap 调用 addEvent,然后将返回的数组从 getNthEvent 方法传递给子组件。
class EventMap {
eventArrays;
constructor() {
this.eventArrays = new Map();
}
addEvent = (id, data) => {
this.eventArrays.has(id)
? this.eventArrays.get(id).push(data)
: this.eventArrays.set(id, [data]);
return this.eventArrays;
}
getNthEvent = (n) => {
const result = [];
for (let key of this.eventArrays.keys()) {
result.push(this.eventArrays.get(key)[n]);
}
return result;
}
}
export default function MarbleDiagram(props) {
const [eventMap, setEventMap] = useState(new EventMap());
// Stream of events for this observable.
const event$ = backpageMessageSubject$.pipe(
filter(message => message.type === 'event'),
map(message => message.event),
filter(event => event.observable === props.observable)
);
useEffect(() => {
const eventSubscription = event$.subscribe(event => {
setEventMap(eventMap => eventMap.addEvent(1, 1)); // This does trigger error.
});
setEventMap(eventMap => eventMap.addEvent(1, 1)); // This does not trigger error.
return () => {
eventSubscription.unsubscribe();
};
}, []);
}
主题来源:
export const backpageMessageSubject$ = new Subject();
完成 setEventMap(eventMap => eventMap.addEvent(1, 1))
后,事件地图的状态是 eventMap.addEvent
的 return 值 ,这不是 EventMap
实例。因此,稍后当您尝试使用它时,它会失败,因为您正在使用的 (Map
) 没有 addEvent
.
由于不能直接修改状态中的项目,您需要更新 EventMap
以便它 return 成为具有添加事件的地图的新实例,而不是改变现有的地图,沿着这些线:
class EventMap {
eventArrays;
constructor(eventArrays = new Map()) { // Note accepting a parameter
this.eventArrays = eventArrays;
}
addEvent = (id, data) => {
// Copy the current map, reusing the same arrays
const eventArrays = new Map(this.eventArrays);
// Get the current array for this `id`
const current = eventArrays.get(id);
if (!current) {
// We don't have it, create a new one in the new map
eventArrays.set(id, [data]);
} else {
// We have it, copy its contents to a new array and
// add the new data to the end, storing it in the
// new map
eventArrays.set(id, [...current, data]);
}
// Create a new EventMap with those arrays and return it
return new EventMap(eventArrays);
}
getNthEvent = (n) => {
const result = [];
for (let key of this.eventArrays.keys()) {
result.push(this.eventArrays.get(key)[n]);
}
return result;
}
}