index.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import {
  2. createContext,
  3. useContext,
  4. useReducer,
  5. useEffect,
  6. ReactNode,
  7. Dispatch
  8. } from "react";
  9. import {
  10. ConfigType
  11. } from "../types";
  12. class NCoreContext<T extends {} | undefined, K extends ConfigType<T>> {
  13. // context:
  14. // @ts-ignore // TODO: Type problem will be fix.
  15. stateContext = createContext<T>({
  16. });
  17. // variables:
  18. state: T;
  19. setState: (state: Partial<T> | any) => void = () => {
  20. };
  21. subscribers: Array<{
  22. func: (state: T) => void;
  23. key: string;
  24. }> = [];
  25. config: K;
  26. // hooks:
  27. useContext = (): T => useContext(this.stateContext);
  28. constructor(state: T, config: K) {
  29. // set initial state:
  30. this.state = state;
  31. this.config = config;
  32. if(config.isSaveState && config.onSetStateFromStorage) {
  33. const savedState = config.onSetStateFromStorage();
  34. if(savedState) {
  35. this.state = {
  36. ...state,
  37. ...savedState
  38. };
  39. }
  40. }
  41. }
  42. // event emitter:
  43. emit = (state: T) => {
  44. this.subscribers.forEach(subscriber => {
  45. subscriber.func(state);
  46. });
  47. };
  48. // listeners:
  49. addEventListener = (key: string, func: (state: T) => void) => {
  50. this.subscribers.push({
  51. func,
  52. key
  53. });
  54. };
  55. removeEventListener = (key: string) => {
  56. const funcIndex = this.subscribers.findIndex(subscriber => subscriber.key === key);
  57. if(funcIndex > -1) {
  58. this.subscribers.splice(funcIndex, 1);
  59. }
  60. };
  61. removeAllListeners = () => {
  62. this.subscribers = [];
  63. };
  64. // context provider:
  65. Provider = ({
  66. children
  67. }: {
  68. children: ReactNode;
  69. }) => {
  70. const StateContextRenderer = this.stateContext;
  71. const [state, setState]: [T, Dispatch<Partial<T>>] = useReducer((state: T, nextState: Partial<T>) => {
  72. const newState = {
  73. ...state,
  74. ...nextState
  75. };
  76. this.state = newState;
  77. this.emit(this.state);
  78. if(this.config.isSaveState && this.config.onStorageUpdate) {
  79. this.config.onStorageUpdate(this.state);
  80. }
  81. return newState;
  82. }, this.state);
  83. useEffect(() => {
  84. this.setState = setState;
  85. }, []);
  86. return <StateContextRenderer.Provider
  87. value={state}
  88. >
  89. {children}
  90. </StateContextRenderer.Provider>;
  91. };
  92. };
  93. export default NCoreContext;