Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot figure out how to declare #24

Open
FrozenKiwi opened this issue Apr 13, 2019 · 3 comments
Open

Cannot figure out how to declare #24

FrozenKiwi opened this issue Apr 13, 2019 · 3 comments

Comments

@FrozenKiwi
Copy link

I don't know whether to post this here or in TypeScript, and it's a request for help (not an issue at all) - but this seems to be an awfully wonky question that only makes sense with your fairly complex typesafety stuff. So here goes..

In short - I have a

class FXRateReducer implements ImmerReducer<initialState> extends IActions {... }

IActions defines the functions on this class. Because this class includes saga's, and I need to be able to call from one saga to the next by using put. Because of this I want to access the actionCreators on this class.

 actions: ActionCreators<IActions>;  // <-- member of FXRateReducer

The above fails to compile because IActions are not derived from ImmerReducerClass. However, if I change that definition to include it:

interface IActions extends ImmerReducerClass

I get the following

TS2420: Class 'FxRateReducer' incorrectly implements interface 'IActions'.
  Type 'FxRateReducer' provides no match for the signature 'new (...args: any[]): ImmerReducer<any>'.

Which is very strange, because FXRateReducer was previously passed into createActionCreators, which means it should be a valid template argument. I also can't seem to add this function in, it just seems to be ignored.

I can't seem to get past this point. I would love to have access to type-safe actions from within the FXRateReducer, but seem to be stuck here.

The end goal is to have a parent template class which provides access to actions to all sub-children, and also allows overriding of customName as I need multiple instances of the same reducer type.

Understandable if you don't have time/desire to help; your work is awesome and I appreciate it.

@FrozenKiwi
Copy link
Author

I also can't just directly write:

function actions(r: FxRateReducer) {
return r._actions as ActionCreators<FxRateReducer>
}

I get the same error: FXRateReducer does not satisfy the constriant...

@yrral86
Copy link

yrral86 commented Dec 14, 2019

I'm fairly new to redux, but my understanding is that you should not be dispatching actions from inside a reducer. I'm not sure what redux would do if you dispatched in the middle of it handling a reduction, but I doubt it would be good. We use a separate class to contain our sagas and keep our reducer class functionality restricted to state updates. The saga class contains a reference to the reducer class. As someone who is still trying to figure out the redux world, I would be interesting in hearing more about your use case if you have a good reason why splitting the sagas from the reducers is not ideal.

@FrozenKiwi
Copy link
Author

FrozenKiwi commented Dec 19, 2019

I've gone through a lot of iterations since this question. My main goal was to have a way to define all my functionality in one place - rather than store of state, I think of it more like an API, or the VM in MVVM, where the client (front end) doesn't know and doesn't care about the difference between a saga and an update.

IOW: for a given module I might have two functions that both update data. From from the websites point-of-view, there is no conceptual difference between these actions. One just happens to involve a fetch.

interface IActions {

  setActiveCurrency(c: Currency): void; // <-- Regular state update

  updateAtTime(t: number): Generator<any>; // <-- Is saga, triggers fetch/update actions
}

The implementation of setActiveCurrency is a regular reducer action and just updates state, and fetchAtTime is an asynchronous action implemented as a saga. The saga can't directly set data on the ImmerReducer, it must dispatch an action to update state (using yield put). To make this easy on myself, I've extended the ImmerReducer to more-or-less handle the difference between these kinds of functions behind the scenes. My goal is to have the saga completely transparent to the person implementing or using IActions.

Does all this make sense to you? I am/was pretty new to Redux too, and approached it with a lot of traditional software dev expectations that probably led me down the wrong track. Specifically, I'm not sure what you mean by

The saga class contains a reference to the reducer class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants