How to use redux-orm with redux and redux-toolkit - react-redux

It's so funny that I'm using redux-orm but found it's hard to work with react-redux (though it's called redux-orm) on my end.
I got TypeError: Cannot read property 'Article' of undefined by using your method.
Let me sidetrack this question a little bit.
Is there any more popular ORM library than redux-orm, it's only has few examples on the internet.
Article.js
```
class Article extends Model {
static reducer(action, Article, session) {
switch (action.type) {
case 'load_all':
action.payload.forEach(articleData=>{
Article.create(articleData);
})
return session;
break;
}
return undefined;
}
}
Article.modelName = 'Article'
Article.fields = {
id: attr(), // non-relational field for any value; optional but highly recommended
name: attr(),
};
export default Article;
```
orm.js
const orm = new ORM ({
stateSelector: state => state.orm,
});
orm.register(Article);
ArticleList.js
const articlesSelector = createSelector(orm.Article);
const ormArticles = useSelector(state => articlesSelector(state, null));

Related

NestJS IntersectionType from #nestjs/swagger does not validate the combined class fields

In following up from this question, I am trying to ensure the validation remains and works. However, my combined class does not validate the included fields.
For instance, I have a basic AdminCodeDTO that sepcifies the AdminCode is required, has a valid value (1-999)
import { IsNumber, Min, Max, IsDefined } from '#nestjs/class-validator';
import { ApiProperty, ApiResponseProperty } from '#nestjs/swagger';
export class AdminCodeDTO {
#ApiProperty({
description: 'Sweda Administration Code used for time tracking that is not part of a mantis.',
})
#ApiResponseProperty({ example: 5 })
#IsDefined() #IsNumber() #Min(1) #Max(999) public AdminCode: number;
constructor(AdminCode?: number) {
this.AdminCode = AdminCode;
}
}
Testing this class works, and the validation will return the errors:
import { validate } from '#nestjs/class-validator';
import { ValidationError } from '#nestjs/common';
import { AdminCodeDTO } from './admin-code-dto';
describe('AdminCodeDto', () => {
let TestDTO: AdminCodeDTO;
beforeEach( () => {
TestDTO = new AdminCodeDTO(5);
});
it('should be defined', () => {
expect(TestDTO).toBeDefined();
});
it('should have the AdminCode value set', () => {
expect(TestDTO.AdminCode).toBe(5);
});
it('should allow creation with an empty constructor', () => {
expect(new AdminCodeDTO()).toBeDefined();
});
it('should generate the DTO errors', async () => {
const DTOValidCheck: AdminCodeDTO = new AdminCodeDTO();
const Errors: Array<ValidationError> = await validate(DTOValidCheck);
expect(Errors.length).toBe(1);
expect(Errors[0].constraints['isDefined']).toBe('AdminCode should not be null or undefined');
expect(Errors[0].constraints['isNumber']).toBe('AdminCode must be a number conforming to the specified constraints');
expect(Errors[0].constraints['max']).toBe('AdminCode must not be greater than 999');
expect(Errors[0].constraints['min']).toBe('AdminCode must not be less than 1');
});
});
To then build a simple DTO combining 2 fields to do the testing, I create a description DTO as well, to add that field for this simple example.
import { IsDefined, IsString, MaxLength, MinLength } from '#nestjs/class-validator';
import { ApiProperty, ApiResponseProperty } from '#nestjs/swagger';
export class DescriptionDTO {
#ApiProperty({
description: '',
minLength: 3,
maxLength: 20
})
#ApiResponseProperty({ example: 'Sick Day' })
#IsDefined() #IsString() #MaxLength(20) #MinLength(3) public Description: string;
constructor(Description?: string) {
this.Description = Description;
}
}
I then use the IntersectionType of #nestjs/swagger, to combine the AdminCodeDTO, with a new description field for the payload.
import { IsDefined, IsString, MaxLength, MinLength } from '#nestjs/class-validator';
import { ApiProperty, ApiResponseProperty, IntersectionType} from '#nestjs/swagger';
import { AdminCodeDTO } from './admin-code-dto';
export class AdmininstrationCodesDTO extends IntersectionType(
AdminCodeDTO,
DescriptionDTO
)
{
constructor(AdminCode?: number, Description?: string) {
this.AdminCode = AdminCode;
this.Description = Description;
}
My test however, while all the columns are defined, the validation does not work.
import { AdmininstrationCodesDTO } from './admininstration-codes-dto';
describe('AdmininstrationCodesDTO', () => {
let TestDTO: AdmininstrationCodesDTO;
beforeEach( () => {
TestDTO = new AdmininstrationCodesDTO(77, 'Test Admin Code');
})
it('should be defined', () => {
expect(TestDTO).toBeDefined();
});
it('should be defined when launched without parameters', () => {
expect(new AdmininstrationCodesDTO()).toBeDefined();
})
it.each([
['AdminCode', 77],
['Description', 'Test Admin Code'],
])('should have the proper field {%s} set to be %d', (FieldName, Expected) => {
expect(FieldName in TestDTO).toBe(true);
expect(TestDTO[FieldName]).toBe(Expected);
});
// This test fails as the validation settings are not enforced. Working on any of the DTOs directly though, the validation is confirmed.
it('should generate the DTO errors', async () => {
const TestDTO: AdmininstrationCodesDTO = new AdmininstrationCodesDTO();
const Errors: Array<ValidationError> = await validate(TestDTO, );
expect(Errors.length).toBe(8);
});
});
EDIT: This also causes a problem in my Swagger UI documentation, where this method now prevents my request schemas from showing the data. When I define my fields directly in the DTO (without IntersectionType) the fields show up in the request schema for Swagger. I have the CLI functions enabled in the project.json (NX monorepo).
As found out from your GitHub Issue (thank you for that by the way) you were using #nestjs/class-validator and #nestjs/class-transformer for the validator and transformer packages. #nestjs/mapped-types uses the original class-valdiator and class-transformer packages and these packages use an internal metadata storage device rather than the full Reflect API and metadata storage, so when Nest tried to copy over the metadata from class-validator there was none found because of the use of #nestjs/class-validator, which ended up in having no metadata present for the IntersectionType request

Strapi V4 how to modify data response for a component (dynamic zone)

Imagine a case where an editor adds a “Latest Products” component to a page using dynamic zone: they add a title, a summary, and then the latest products will automatically be fetched to be available in the response. How can I add this data to the response of the component?
I know we can override the response for content types using a custom controller, but I can't find anything for how to modify the response for a component.
Maybe there's an alternative approach I haven't thought of, but coming from a Drupal preprocess-everything background this is all I can think of.
Any help appreciated!
I'm sure this isn't the best way, but I created a service for components that can be used in the content type controller to modify the response. Any improvements appreciated!
/api/custom-page/controllers/custom-page.js
'use strict';
/**
* custom-page controller
*/
const { createCoreController } = require('#strapi/strapi').factories;
module.exports = createCoreController('api::custom-page.custom-page', ({ strapi }) => ({
async find(ctx) {
const componentService = strapi.service('api::components.components');
let { data, meta } = await super.find(ctx);
data = await Promise.all(data.map(async (entry, index) => {
if(entry.attributes.sections){
await Promise.all(entry.attributes.sections.map(async (section, index) => {
const component = await componentService.getComponent(section);
entry.attributes.sections[index] = component;
}));
}
return entry;
}));
return { data, meta };
},
}));
/components/services/components.js
'use strict';
/**
* components service.
*/
module.exports = () => ({
getComponent: async (input) => {
// Latest products
if(input.__component === 'sections.latest-products'){
input.products = 'customdatahere';
}
return input;
}
});

How do items in an object from one function transfer into another function?

I am learning react redux, I am using firebase for storing data.
I installed thunk middleware. Everything works, I just don't understand why.
As I understand it, the const expense is an object which is in another function's scope. How can addExpense gets access to it?
export const addExpense = (expense) => ({
type: 'ADD_EXPENSE',
expense
});
export const startAddExpense = (expenseData = {}) => {
return (dispatch) => {
const {
description = '',
note = '',
amount = 0,
createdAt = 0
} = expenseData;
const expense = { description, note, amount, createdAt };
database.ref('expenses').push(expense).then((ref) => {
dispatch(addExpense({
id: ref.key,
...expense
}));
});
};
};
startAddExpense is passing the const expense object to your addExpense function, along with an id field. It just so happens that the argument to addExpense is also called expense, which is where you might be getting confused.
Hope that clears it up.

Using graphql-tools to mock a GraphQL server seems broken

I've followed the documentation about using graphql-tools to mock a GraphQL server, however this throws an error for custom types, such as:
Expected a value of type "JSON" but received: [object Object]
The graphql-tools documentation about mocking explicitly states that they support custom types, and even provide an example of using the GraphQLJSON custom type from the graphql-type-json project.
I've provided a demo of a solution on github which uses graphql-tools to successfully mock a GraphQL server, but this relies on monkey-patching the built schema:
// Here we Monkey-patch the schema, as otherwise it will fall back
// to the default serialize which simply returns null.
schema._typeMap.JSON._scalarConfig.serialize = () => {
return { result: 'mocking JSON monkey-patched' }
}
schema._typeMap.MyCustomScalar._scalarConfig.serialize = () => {
return mocks.MyCustomScalar()
}
Possibly I'm doing something wrong in my demo, but without the monkey-patched code above I get the error regarding custom types mentioned above.
Does anyone have a better solution than my demo, or any clues as to what I might be doing wrong, and how I can change the code so that the demo works without monkey-patching the schema?
The relevant code in the demo index.js is as follows:
/*
** As per:
** http://dev.apollodata.com/tools/graphql-tools/mocking.html
** Note that there are references on the web to graphql-tools.mockServer,
** but these seem to be out of date.
*/
const { graphql, GraphQLScalarType } = require('graphql');
const { makeExecutableSchema, addMockFunctionsToSchema } = require('graphql-tools');
const GraphQLJSON = require('graphql-type-json');
const myCustomScalarType = new GraphQLScalarType({
name: 'MyCustomScalar',
description: 'Description of my custom scalar type',
serialize(value) {
let result;
// Implement your own behavior here by setting the 'result' variable
result = value || "I am the results of myCustomScalarType.serialize";
return result;
},
parseValue(value) {
let result;
// Implement your own behavior here by setting the 'result' variable
result = value || "I am the results of myCustomScalarType.parseValue";
return result;
},
parseLiteral(ast) {
switch (ast.kind) {
// Implement your own behavior here by returning what suits your needs
// depending on ast.kind
}
}
});
const schemaString = `
scalar MyCustomScalar
scalar JSON
type Foo {
aField: MyCustomScalar
bField: JSON
cField: String
}
type Query {
foo: Foo
}
`;
const resolverFunctions = {
Query: {
foo: {
aField: () => {
return 'I am the result of resolverFunctions.Query.foo.aField'
},
bField: () => ({ result: 'of resolverFunctions.Query.foo.bField' }),
cField: () => {
return 'I am the result of resolverFunctions.Query.foo.cField'
}
},
},
};
const mocks = {
Foo: () => ({
// aField: () => mocks.MyCustomScalar(),
// bField: () => ({ result: 'of mocks.foo.bField' }),
cField: () => {
return 'I am the result of mocks.foo.cField'
}
}),
cField: () => {
return 'mocking cField'
},
MyCustomScalar: () => {
return 'mocking MyCustomScalar'
},
JSON: () => {
return { result: 'mocking JSON'}
}
}
const query = `
{
foo {
aField
bField
cField
}
}
`;
const schema = makeExecutableSchema({
typeDefs: schemaString,
resolvers: resolverFunctions
})
addMockFunctionsToSchema({
schema,
mocks
});
// Here we Monkey-patch the schema, as otherwise it will fall back
// to the default serialize which simply returns null.
schema._typeMap.JSON._scalarConfig.serialize = () => {
return { result: 'mocking JSON monkey-patched' }
}
schema._typeMap.MyCustomScalar._scalarConfig.serialize = () => {
return mocks.MyCustomScalar()
}
graphql(schema, query).then((result) => console.log('Got result', JSON.stringify(result, null, 4)));
I and a few others are seeing a similar issue with live data sources (in my case MongoDB/Mongoose). I suspect it is something internal to the graphql-tools makeExecutableSchema and the way it ingests text-based schemas with custom types.
Here's another post on the issue: How to use graphql-type-json package with GraphQl
I haven't tried the suggestion to build the schema in code, so can't confirm whether it works or not.
My current workaround is to stringify the JSON fields (in the connector) when serving them to the client (and parsing on the client side) and vice-versa. A little clunky but I'm not really using GraphQL to query and/or selectively extract the properties within the JSON object. This wouldn't be optimal for large JSON objects I suspect.
If anyone else comes here from Google results, the solution for me was to add the JSON resolver as parameter to the makeExecutableSchema call. It's described here:
https://github.com/apollographql/apollo-test-utils/issues/28#issuecomment-377794825
That made the mocking work for me.

Angular2 : Reduce number of Http calls

I'm using Angular2 RC5 with an ASP.NET Core server that makes the API calls to get my data.
I'm actually wondering if there is a way to reduce the number of http calls you make with Angular2, because I fear there will be a lot if I keep using components the way I do. Here is a concrete example.
I want to get a text value from the database, which is defined by an ID and a Language. I then made the following component :
dico.component.ts
#Component({
selector: 'dico',
template: `{{text}}`,
providers: [EntitiesService]
})
class Dico implements AfterViewInit {
#Input() private id: string;
#Input() private lang: string;
private text: string = null;
// DI for my service
constructor(private entitiesService: EntitiesService) {
}
ngAfterViewInit() {
this.getDico();
}
// Call the service that makes the http call to my ASP Controller
getDico() {
this.entitiesService.getDico(this.id, this.lang)
.subscribe(
DicoText => this.text = DicoText
);
}
}
#Component({
template: `<dico [id] [lang]></dico>`,
directives: [Dico]
})
export class DicoComponent {
}
Here is the code from my service :
entities.service.ts
getDico(aDicoID: string, aLangue: string) {
// Parameters to use in my controller
let params = new URLSearchParams();
params.set("aDicoID", aDicoID);
params.set("aLangue", aLangue);
// Setting up the Http request
let lHttpRequestBody = params.toString();
let lControllerAction: string = "/libelle";
let lControllerFullURL: string = this.controllerURL + lControllerAction;
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
return this.http.post(lControllerFullURL, lHttpRequestBody, options)
.map((res: any) => {
// Parsing the data from the response
let data = res.json();
// Managing the error cases
switch (data.status) {
case "success":
let l_cRet: string = data.results;
if (l_cRet != null && !l_cRet.includes("UNDEFINED")) {
return data.results;
} else {
throw new Error("Erreur récupération Dico : " + l_cRet);
}
case "error":
throw new Error("Erreur récupération Dico : " + data.message);
}
}
).catch(this.handleError);
}
Then I can use my newly made component in my app :
randomFile.html
<dico id="201124" lang="it"></dico>
<dico id="201125" lang="en"></dico>
<dico id="201126" lang="fr"></dico>
But this application will eventually use hundreds of these "dico" and I was wondering how I could manage some pre-fetch or something like that before the app fully loads. Does it even matter ? Will that affect performance in the long term ?
Any advice would be greatly appreciated.
EDIT : These dico allow me to fetch from the database a text translated into the langage I want. Here, in the example above, I have 3 "dico" that will output some text in italian, french, and english.
My application will use a lot of them, as every text in every menu will be a "dico", and the problem is that there will be a lot of them, and right now for every "dico" I make, my service is called and makes one http call to get the data. What I want is to somehow define all my dicos, call the service which will give me the text of all my dicos in an array to avoid making several calls (but I don't really know how to do that).
A basic untested approach (I don't know observables too well myself)
class DicoService {
private subjects = {}
private ids = [];
getDico(String id):Observable<Dico> {
var s = this.subjects[id];
if(!s) {
this.ids.push(id);
s = new Subject();
this.subjects[id]=s;
}
return s.asObservable().share().first();
}
sendRequest() {
http.get(....) /* pass this.ids */
map(response => response.json())
.subscribe(data => {
for(item in data) { // don't know how to iterate exactly because I don't know how the response will look like
this.subject[item.id].next(item.langText);
}
// you might cache them if other components added by the router also request them
// this.subjects = {};
// this.ids = []
});
}
}
<dico [text]="dicoService.getDico('someId') | async"></dico>
ngAfterViewInit() {
this.dicoService.sendRequest();
}

Resources