javascript - 无法在订阅主体内的 setState Hook 中调用先前状态的对象方法

标签 javascript reactjs rxjs setstate

尝试使用 useState 钩子(Hook)更新对象状态在 RxJS 主题订阅体内部不起作用,但在其外部起作用。 (用第二段代码中的注释进行注释)

我收到的错误是:TypeError: eventMap.addEvent is not a function

我的目标是使用 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.addEvent 的,它不是 EventMap 实例。因此,稍后当您尝试使用它时,它会失败,因为您正在使用的内容(Map)没有addEvent

由于状态中的项目不得直接修改,因此您需要更新 EventMap 以便它返回具有添加事件的 map 的新实例,而不是改变现有 map ,以及这些行:

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;
    }
}

关于javascript - 无法在订阅主体内的 setState Hook 中调用先前状态的对象方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60529036/

相关文章:

javascript - AWS JS SDK 类型错误 : STS is not a constructor

reactjs - 如何在挂载时触发操作,但在 redux 存储加载之后

Angular 6 - 每 10 秒运行一次服务方法

javascript - 有没有办法将 rxjs 导入普通的 js web 自定义组件?

javascript - 如何检查多个HTML5视频的音频

php - 使用 php javascript html 和 xml 制作论坛

javascript - 表单提交不适用于 WordPress 管理中的下拉更改

javascript - 负载第一师应该是开放的

javascript - setState 不是 React Native 中的函数

angular - 如何在 Angular 6 中组合两个相同类型的可观察数组?