facebookarchive / flux

Application Architecture for Building User Interfaces
https://facebookarchive.github.io/flux/
Other
17.42k stars 3.47k forks source link

Is this code a good way to update react component from dispatch in OOP class object? #484

Closed neo-sam closed 4 years ago

neo-sam commented 4 years ago

Case Background

I'm going to make a simplified photoshop like app using react.js, which has a thousands of state such like using tools, drawing history, brush point, brush size, ........ etc.

I have considered using redux, mobx, react context to manage all kinds of the app states, but they are still too "stupid" in my case:

So, I think use typescript oop program skills and flux design mode is right for me. However, there is too few technical documentation about flux. So, can you tell me the code below a good way to practice flux with oop?

Code

import React, { useEffect, useCallback, useState } from 'react';
import { Dispatcher } from 'flux';

//#region you can put this stories code to a storybook project
export default { title: 'Flux' };

export function Space() {
  useUpdateAfterDispatch(myObject.dispatcher);

  return (
    <div>
      <p>current value: {myObject.value}</p>
      <button onClick={() => {
          myObject.addText();
        }} >update</button>
    </div>
  );
}
//#endregion

class Model {
  readonly dispatcher = new Dispatcher<null>();

  protected _value: string;
  get value() {
    return this._value;
  }

  constructor(initial: string) {
    this._value = initial;
  }

  public addText() {
    this._value += ' added sth';
    this.dispatcher.dispatch(null);
  }
}

const myObject = new Model('initial');

/** hook for auto register/unregister callback */
function useDispatcherRegister<T>(
  dispatcher: Dispatcher<T>,
  callback: (payload: T) => void,
  deps?: React.DependencyList
) {
  // memo my callback with deps array
  const _callback = useCallback(callback, deps ?? []);

  useEffect(() => {
    const id = dispatcher.register(_callback);
    return () => dispatcher.unregister(id);
  }, [_callback, dispatcher]);
}

/** hook for auto render update after dispatch call */
function useUpdateAfterDispatch<T>(dispatcher: Dispatcher<T>) {
  const [, setUpdate] = useState(false);
  useDispatcherRegister(dispatcher, () => {
    // flip the value to trigger update
    setUpdate(flag => !flag);
  });
}

I'm sure I wouldn't do heavy calculate on Model.addText() method, and do some optimization in other multi states components.

Is the code above obey flux design principle, or any problems relating to my hooks?

neo-sam commented 4 years ago

Oh I know, I didn't obey flux design model at all.

Flux: Action -> Dispatch -> Store -> View Me: Action -> Model(Store) -> Dispatch -> View

I'm using eventbus subscribe design model actually.

If there are no trouble, you can close this issue.

yangshun commented 4 years ago

Since this question is asking for opinions and help, you would get better replies and reach a wider audience by asking on Stack Overflow instead.