stremio-web/src/common/useModelState.js
2022-04-20 21:18:43 +03:00

67 lines
2.1 KiB
JavaScript

// Copyright (C) 2017-2022 Smart code 203358507
const React = require('react');
const throttle = require('lodash.throttle');
const isEqual = require('lodash.isequal');
const { useRouteFocused } = require('stremio-router');
const { useServices } = require('stremio/services');
const useModelState = ({ init, action, ...args }) => {
const { core } = useServices();
const routeFocused = useRouteFocused();
const mountedRef = React.useRef(false);
const [model, timeout, map] = React.useMemo(() => {
return [args.model, args.timeout, args.map];
}, []);
const [state, setState] = React.useReducer(
(prevState, nextState) => {
return Object.keys(prevState).reduce((result, key) => {
result[key] = isEqual(prevState[key], nextState[key]) ? prevState[key] : nextState[key];
return result;
}, {});
},
undefined,
() => {
return typeof init === 'function' ?
init()
:
init;
}
);
React.useLayoutEffect(() => {
if (action) {
core.transport.dispatch(action, model);
}
}, [action]);
React.useLayoutEffect(() => {
return () => {
core.transport.dispatch({ action: 'Unload' }, model);
};
}, []);
React.useLayoutEffect(() => {
const onNewStateThrottled = throttle(() => {
const state = core.transport.getState(model);
if (typeof map === 'function') {
setState(map(state));
} else {
setState(state);
}
}, timeout);
if (routeFocused) {
core.transport.on('NewState', onNewStateThrottled);
if (mountedRef.current) {
onNewStateThrottled.call();
}
}
return () => {
onNewStateThrottled.cancel();
core.transport.off('NewState', onNewStateThrottled);
};
}, [routeFocused]);
React.useLayoutEffect(() => {
mountedRef.current = true;
}, []);
return state;
};
module.exports = useModelState;