Closed st-clair-clarke closed 7 years ago
Hi st-claire-clarke!
The first reason you're getting an error is because your addResetEmailDataAction
has no payload. That is, in the line
export const addResetEmailDataAction = userAcf( 'ADD_DATA' )
since you don't specify a payload type, the actions created by this factory are assumed to have no payload. Based on the fact that your addResetEmailDataHandler
function takes an IEmail
as its second argument, I assume you want to be able to create actions with IEmail
as their payload, but note that as written the following is an error:
let email: IEmail
const action = addResetEmailDataAction(email)
// Argument of type IEmail is not assignable to parameter of type 'undefined'.
Because of this, I would guess that what you want instead is
export const addResetEmailDataAction = userAcf<IEmail>( 'ADD_DATA' )
which allows you to call addResetEmailDataAction(email)
which is probably what you want.
Secondly, supposing you make that change you'll still have a type error on the .caseWithAction()
line because .caseWithAction()
expects a handler function which takes (state, action) => state
, by contrast to .case()
whose handler function is (state, payload) => state
. In your example code, the second argument of addResetEmailDataHandler
has type IEmail
which is the payload type, not the action type, so you actually do want to be using .case
here.
Based on the code you posted, I don't see a reason why you would need to be using .caseWithAction()
rather than .case()
- the former is mainly useful when you need to either read meta information from the action or pass the entire action on unchanged to a different handler, but the example code does neither.
Please let me know if I am misunderstanding or if you have further questions. Thanks!
Hi Phillipson, Thanks for your quick reply.
The meta: IMeta type in the IEmai has the definition as shown below:
export interface IMeta { lastEditedBy: string timeStamp: Date }
export class Meta { lastEditedBy: string = '' timeStamp: Date }
I would like to access these data when the store is updated using .caseWithAction(). So, I would like to update a log with the meta data. With this information, what would the complete code look like, including the handler?
Cheers
Any reason this doesn't work?
const userAcf = actionCreatorFactory( '[Admin ResetEmail]' )
export const addResetEmailDataAction = userAcf<IEmail>( 'ADD_DATA' )
export function addResetEmailDataHandler( state: IEmail, email: IEmail ): IEmail {
// In here, you can access the metadata through email.meta.
return Object.assign( {}, state, email )
}
export const resetResetEmailDataAction = userAcf( 'RESET_DATA' )
function resetResetEmailDataHandler( state: IEmail ): IEmail {
return Object.assign( {}, state, new Email() )
}
export const resetEmailDataReducer = reducerWithInitialState( new Email() )
.case( addResetEmailDataAction, addResetEmailDataHandler)
.case( resetResetEmailDataAction, resetResetEmailDataHandler )
}
// Example of creating an addResetEmailAction
const meta = new Meta();
meta.lastEditedBy = "someGuy";
meta.timestamp = new Date();
const email = new Email();
email.address = "example@example.com";
email.meta = meta;
const myAction = addResetEmailAction(email);
// myAction looks like: { type: "ADD_DATA", payload: email }.
Note that the metadata as you've written it is different from the meta field on the action, because IEmail
is not the type of the action, it's the type of the action's payload. If it were the meta field of the action, then the action would appear:
{
type: "ADD_DATA",
payload: {
type: "",
address: ""
},
meta: { lastEditedBy: "", timestamp: <some-date> }
}
but your actions don't look like that, they look like this:
{
type: "ADD_DATA",
payload: {
type: "",
address: "",
meta: { lastEditedBy: "", timestamp: <some-date> }
}
}
Since meta
is just another field on your payload, you don't need to use .caseWithAction
to read it and can just pull it out of .case
.
Closing this for inactivity. Feel free to re-open if you have more questions.
Hi, I have the following:
import actionCreatorFactory from 'typescript-fsa' import { reducerWithInitialState } from 'typescript-fsa-reducers'
import { FormState, IFormState } from '../../shared/shared.store/store.util'
export interface IEmail { address: string type: string meta: IMeta }
export class Email { type: string = '' address: string = '' meta: IMeta }
const userAcf = actionCreatorFactory( '[Admin ResetEmail]' )
export const addResetEmailDataAction = userAcf( 'ADD_DATA' )
export function addResetEmailDataHandler( state: IEmail, email: IEmail ): IEmail { return Object.assign( {}, state, email ) }
export const resetResetEmailDataAction = userAcf( 'RESET_DATA' )
function resetResetEmailDataHandler( state: IEmail ): IEmail { return Object.assign( {}, state, new Email() ) }
export const resetEmailDataReducer = reducerWithInitialState( new Email() ) .caseWithAction( addResetEmailDataAction, addResetEmailDataHandler, ) // ERROR with addResetEmailDataHandler .case( resetResetEmailDataAction, resetResetEmailDataHandler ) }
My .case works but the .caseWithAction does not. I need your help to use my addResetEmailDataHandler handler to work in the .caseWithAction above.
Thanks