尝试使用useState挂钩更新对象状态在RxJS主题订阅主体内部不起作用,但在其外部起作用。 (在第二个代码部分的注释中注释)
我收到的错误是:TypeError: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
的返回值,它不是EventMap
实例。因此,稍后尝试使用它时,它会失败,因为您正在使用的(Map
)没有addEvent
。
由于处于状态的项不能直接修改,因此您需要更新EventMap
,使其返回具有添加事件的新地图实例,而不是按照以下方式更改现有地图:
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;
}
}