无法在订阅体内的 setState 挂钩中调用先前状态的对象方法

Can't call object method on previous state in setState hook inside subscribe body

尝试使用 useState 钩子更新对象状态在 RxJS 主题订阅体内部不起作用,但在它外部起作用。 (在第二个代码部分用注释注释)

我收到的错误是:类型错误:eventMap.addEvent 不是函数

我的目标是使用来自 backpageMes​​sageSubject$ 的事件从 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.addEventreturn 值 ,这不是 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;
    }
}