const React = require('react'); const throttle = require('lodash.throttle'); const { useRouteFocused } = require('stremio-router'); const { useServices } = require('stremio/services'); const useDeepEqualState = require('stremio/common/useDeepEqualState'); const UNLOAD_ACTION = { action: 'Unload', }; const useModelState = ({ model, init, action, timeout, onNewState, map, mapWithCtx }) => { const modelRef = React.useRef(model); const mountedRef = React.useRef(false); const { core } = useServices(); const routeFocused = useRouteFocused(); const [state, setState] = useDeepEqualState(init); React.useLayoutEffect(() => { core.dispatch(action, modelRef.current); }, [action]); React.useLayoutEffect(() => { return () => { core.dispatch(UNLOAD_ACTION, modelRef.current); }; }, []); React.useLayoutEffect(() => { const onNewStateThrottled = throttle(() => { const state = core.getState(modelRef.current); if (typeof onNewState === 'function') { const action = onNewState(state); const handled = core.dispatch(action, modelRef.current); if (handled) { return; } } if (typeof mapWithCtx === 'function') { const ctx = core.getState('ctx'); setState(mapWithCtx(state, ctx)); } else if (typeof map === 'function') { setState(map(state)); } else { setState(state); } }, timeout); if (routeFocused) { core.on('NewState', onNewStateThrottled); if (mountedRef.current) { onNewStateThrottled.call(); } } return () => { onNewStateThrottled.cancel(); core.off('NewState', onNewStateThrottled); }; }, [routeFocused, timeout, onNewState, map, mapWithCtx]); React.useLayoutEffect(() => { mountedRef.current = true; }, []); return state; }; module.exports = useModelState;