Does not exist on type 'DefaultRootState'. TS2339 - react-redux

I am trying to implement react-redux in login-form input values.
I have added values to the redux state, but I cannot access the data individually from the state object.
Here are the details:
In App.js file
console.log(useSelector((state) => state));
gives result {email: "demo#demo.com" , password: "123456"}
. I am not able to access the email inside the state object using
console.log(useSelector((state) => state.email));
It is giving the error that
'email' does not exist on type 'DefaultRootState'. TS2339
Here is the reducer.js file
let formValues = {
email: "",
password: "",
};
export const inputReducer = (state = formValues, action) => {
switch (action.type) {
case "inputValue":
return { ...state, [action.name]: action.inputValue };
default:
return state;
}
};
Here is the action.txt file
export const handleChange = (name: string, inputValue: string) => {
return {
type: "inputValue",
name: name,
inputValue: inputValue,
};
}

I wrote a function to get rid of this problem :
function getProperty<T, K extends keyof T>(o: T, propertyName: K): T[K] {
return o[propertyName]; // o[propertyName] is of type T[K]
}
You have to pass your object as first parameter, then the name of your property (here it is email or password).
If you want to get all your property at once, you have to encapsulate them in an object property like this:
{ value : {email:"alan.turing#gmail.com",password:"123" } }

i may be late but thought to provide solution. Basically this type of error message appears when you don't provide the typing in the useSelector hook
As per the doc React-Redux which states:
Using configureStore should not need any additional typings. You will,
however, want to extract the RootState type and the Dispatch type so
that they can be referenced as needed.
here in your code block the RootState type is missing, this can be declared in your store file as below
import {createStore} from 'redux';
----------
const store = createStore(rootReducer);
export default store;
export type RootState = ReturnType<typeof store.getState>;
And in your .tsx or .jsx file where exactly you want to access your store values using react-redux hook useSelector add the type as below.
useSelector((state:RootState) => state)

Related

Access context from Apollo GraphQL mutation field directive

I have an input type like this:
input PetGiraffe {
name: String #addUserLastName
}
Inside the directive, I need access to the request's context, so that I can add the user's last name to the giraffe's name. Here's the relevant part of what I've got so far:
const addUserLastNameDirective = {
typeDefs: gql`directive #addUserLastName on INPUT_FIELD_DEFINITION`,
transformer: (schema: GraphQLSchema, directiveName = 'addUserLastName') => {
return mapSchema(schema, {
[MapperKind.INPUT_OBJECT_FIELD]: (fieldConfig, fieldName, typeName, schema) => {
const directive = getDirective(schema, fieldConfig, directiveName)?.[0];
if (directive) {
// Need context in here because the user is in the context.
}
},
});
},
};
For queries, I understand you can override the fieldConfig.resolve method and get access to the context that way. But if I try that with this mutation, it throws: field has a resolve property, but Input Types cannot define resolvers.
The closest I could find was this from the graphql-tools docs, but that doesn't solve my problem of accessing the context.

TypeGraphQL createUnionFunction with parameter

I'm trying to implement an extension of typegraphql's createUnionType() function to where I can pass in a class/ObjectType instead of hardcoding, and it will return a union type of both.
What I have so far doesn't work but I feel like it's possible. Could anyone provide any insight? Maybe it's not possible?
typedefs
import { ObjectType, Field, createUnionType, ClassType } from "type-graphql";
#ObjectType()
export default class MutationSuccess {
#Field()
success: boolean = true;
}
// Doesn't work
export const MutationResponse = (objectType: ClassType) => createUnionType({
name: 'MutationResponseType',
types: () => [MutationSuccess, objectType],
})
How I'm trying to use it in my resolver
#Resolver()
export default class RelationResolver {
#Mutation(() => MutationResponse(Relation), { description: 'follow user' })
async follow(
#Arg('relationInput') relationInput: RelationInput
): Promise<Relation | MutationSuccess> {
// do some stuff
}
}
error
UnhandledPromiseRejectionWarning: Error: Cannot determine GraphQL output type for follow
The Relation class need to be decorated with #ObjectType and the union type name has to be unique.

Why does React Flow reject this approach?

I'm building a React app with the Context API and React Hooks. I'm trying to follow best practices. To that end I'm using Flow and am trying to adhere to its warnings.
I have a situation where once the user logs in, I want to store some data about this user in a SessionContext I've built. Given that there are only 3 pieces of data right now and they're all primitive, I thought it made sense to have just one Reducer Action:
export const sessionReducer = (state: SessionState, action: SessionAction) => {
switch (action.type) {
case UPDATE_SESSION_PROP: {
return {
...state,
[action.propName]: action.payload
};
}
default: {
return state;
}
}
}
Here are the Action types I created to account for the 3 types of data:
export type UserEmailAction = {type: 'UPDATE_SESSION_PROP',
propName: 'currentUserEmail',
payload: string};
export type UserAccessLevelAction = {type: 'UPDATE_SESSION_PROP',
propName: 'currentUserAccessLevel',
payload: number};
export type CurrentCompanyNameAction = {type: 'UPDATE_SESSION_PROP',
propName: 'currentCompanyName',
payload: string};
In my SessionContext I combine these 3 Action types as follows, and then define a Dispatch type from that:
export type SessionAction =
| UserEmailAction
| UserAccessLevelAction
| CurrentCompanyNameAction;
type Dispatch = (action: SessionAction) => void;
There are 4 warning messages over top of sessionReducer in this code:
const [state: SessionState, dispatch: Dispatch] = useReducer(sessionReducer, defaultState);
The messages are akin to this: "Cannot call useReducer with sessionReducer bound to reducer because number [1] is incompatible with string [2] in property currentCompanyName of the return value."
Did I define the Action types incorrectly or is Flow just not intelligent enough differentiate the 3 patterns? By the way, this approach seems to work fine when run.
Flow isn't intelligent enough. But you can use different approach that flow will understand:
type SessionState = {
currentUserEmail: string,
currentUserAccessLevel: number,
currentCompanyName: string,
};
type SessionAction = {
type: 'UPDATE_SESSION_PROP',
payload: $Shape<SessionState>,
};
const sessionReducer = (state: SessionState, action: SessionAction) => {
switch (action.type) {
case UPDATE_SESSION_PROP: {
return {
...state,
...action.payload
};
}
default: {
return state;
}
}
}
https://flow.org/try/#0JYWwDg9gTgLgBAbzgVwM4FMBK6AmyDG6UcAvnAGZQQhwDkU6AhvjLQNwBQH+EAdqvACqABQAiAQQAqAUQD6AZWnz5ASQDyAOVnDMa4XAC8dERJkKlqzdt3D2XGAE8w6OPPSpUwPvJiMYLowQOODh8ZCgGXhhBDChpEEZgABsALjgBKGBeAHMAGmDQ8Mjo2PF8Qg8AGXQAN3RUuF5kEAAjInyQsIj0KIBhajBGXgcNRhB0NIysvI4STg50AA9IWDhHZ1d3Tz4ymC9eQ0QC9YnjMSk5RWV1LR09Wg64QYckiEYcNIASeQALRmcADxuDz7Hx+dAAPnyc3sThcomAqEGMHwP0OAApmHs+GlgdteLt9gBKQwQuA1CDAHDzHDofBJRgMcmMuC08iMZBJGBg-y4rag3z+eY8fjwDAgvjYPCEYhGdECcF8iW8HnoXJwLH7JX4wl8EkGMlBEKoADuwBRaMxLH2ADoTiSjSFQowMHATBdzNcrHdhGlHU64AwYOEDv6A3AbZGFf5HuGI5HNXwbc9Xu8CgGYRmuAG2RyuX7006gyH0oL0JwsyESLMuCKBHAANrR054gXg9U4RHI1FpBFIvyogC6hzQWFwBCI8v5kvHMo76HZnO5ZaJbCAA
It will reduce overall amount of code also so I don't think it's too bad.

Cannot initialize the state of ngrx (v. 4.x) store

I am currently looking into using the ngrx store (v. 4.0.3) for state management. It seems like a great project.
I have hit a bit of a bump in the road while trying to initialize the state of my store. The documentation makes it look rather simple, but yet I am not able to see where I am going wrong.
Here's the relevant code snippets:
in app.state.ts
export interface AppState {
searchText: string;
}
In search-text.reducer.ts
export const UPDATE = 'UPDATE';
export class UpdateSearchTextAction implements Action {
readonly type: string = UPDATE;
constructor(public readonly text: string) {}
}
export function searchTextReducer(state: string, action: UpdateSearchTextAction) {
switch(action.type) {
case UPDATE:
return action.text;
}
};
In app.module.ts
export const reducers: ActionReducerMap<AppState, UpdateSearchTextAction> = {
searchText: searchTextReducer
};
export const initialState: InitialState<AppState> = {
searchText: 'sds'
};
....
imports: [
....
StoreModule.forRoot(reducers, initialState)
]
in some Component
constructor(private store: Store<AppState>) {
this.searchBoxText = store.select('searchText');
this.searchBoxText.subscribe(text => console.log('value = [' + text + "]"));
}
So, when the application loads, I would expect to see the following logged to the console:
value = [sds]
yet I see
value = [undefined]
Later, once I start typing in an input that triggers an UpdateSearchTextAction the console does indeed log the correct value. So it seems like I've setup the store correctly.
There is probably something real simple I'm missing. Can anyone provide some advice?
Since you are having it as readonly you are not allowed to assign the value,
export class UpdateSearchTextAction implements Action {
readonly type: string = UPDATE;
constructor(public text: string) {}
}
And you need to dispatch the value using a dispatch statement
this.store.dispatch(new UpdateSearchTextAction.UPDATE(<<string>>));
You must specify default value for state argument and return the same state if no action matches. Try to change your reducer to the following:
export function searchTextReducer(state: string = '', action: UpdateSearchTextAction) {
switch(action.type) {
case UPDATE:
return action.text;
default:
return state;
}
};

Object mutations in graphQL

Here is my EventAttendee Object.
const EventAttendee = new GraphQLInputObjectType({
name: 'EventAttendee',
fields: () => ({
attendeeName: {type: GraphQLString},
personalizedDateSelection: {type: new GraphQLInputObjectType()}
})
});
The personalizedDateSelection property is an dynamic one and its properties are not known now. So, In this case, I have given GraphQLInputObjectType().
But it gives an error stating EventAttendee.personalizedDateSelection field type must be Output Type.
How to define an ObjectType whose properties are not known ?
I believe you want to define an InputObjectType and not an ObjectType as stated.
With that said, what you can do is to declare personalizedDateSelection as a string for now, and then later adapt it as needed with a custom input object, once you know what it should contain. GraphQLInputObjectType is used to define new input object types, it isn't a type per se.
I wanted personalizedDateSelection property of EventAttendee to be of objectType but I dont know those properties in advance, but I am sure that it is of Object type.
So declaring this as GraphQLScalarType was the correct way to do it. Check out about GraphQLScalarType. But we need to create a custom scalar type. All scalar types can be of input type. So here is my implementation:
const PersonalizedDateSelection = new GraphQLScalarType({
name: 'PersonalizedDateSelection',
serialize: value => {
return value;
},
parseValue: value => {
return value;
},
parseLiteral: ast => {
console.log("coming in parseLiteral");
console.log(ast);
let value = {};
if (ast.kind !== Kind.OBJECT) {
throw new GraphQLError("Query error: Can only parse object but got a: " + ast.kind, [ast]);
}
ast.fields.forEach(field => {
value[field.name.value] = parseJSONLiteral(field.value);
});
return value;
}
});

Resources