Sunday, May 27, 2018

Postgres timestamp





Happy Coding!

Postgres UTC data type

There's really no type of timestamp with time zone with Postgres. Time zone is not stored, everything is stored as UTC. The time zone is only used for presentation purposes.











Happy Coding!

Saturday, May 26, 2018

Typescript properties concatenation

TypeScript has a unique functionality, it can concatenate properties inline.

Given these following classes from C#
public class PagedDto<T>
{
    public IList<T> Data { get; set; }
    public int Pages { get; set; }
}

public class PagedCityDto
{
    public int CityId { get; set; }
    public string CityName { get; set; }        

    public int StateId { get; set; }
    public string StateName { get; set; }
}   


The above are translated to these:
export interface IPagedDto<T>
{
    data: T[];
    pages: number;
}

export interface IPagedCityDto
{
    cityId: number;
    cityName: string;

    stateId: number;
    stateName: string;
}


Then the following properties concatenation..
interface IComponentState
{
    grid: IPagedDto<IPagedCityDto> & {
        loading: boolean;
    };
}

..is expanded to:
interface IComponentState
{
    grid: {
        data: IPagedCityDto[];
        pages: number;
        loading: boolean;
    };
}


Why would we do concatenation? Why not just put the loading property out-of-band from grid property like this?
interface IComponentState
{
    grid: IPagedDto<IPagedCityDto>;
    isLoading: boolean;   
}

Well we need those three properties to be grouped in one property (i.e., grid) as they are related to each other. Besides, putting the isLoading outside of grid object is a cognitive load for other devs reading your code, the code would give them impression that isLoading property is related to the whole component and not specific to grid. One might say, that it can be renamed to isGridLoading to signify it pertains to the grid only.

interface IComponentState
{
    grid: IPagedDto<IPagedCityDto>;
    isGridLoading: boolean;   
}

Still the best way to write readable code is to group related things together, not just by naming convention, but through whatever the best mechanism the programming language can provide to the developer. The following is better than the code above.

interface IComponentState
{
    grid: {
        data: IPagedCityDto[];
        pages: number;
        loading: boolean;
    };
}

Better yet, use TypeScript's built-in concatenation mechanism:
interface IComponentState
{
    grid: IPagedDto<IPagedCityDto> & {
        loading: boolean;
    };
}

There's also a symmetry when grouped properties are used:

<ReactTable
    manual={true}
    columns={[
        {
            Header  : <Typography>City</Typography>,
            accessor: 'cityName',
            id      : 'City',
            Cell    : row => (
                <Typography>
                    <a href={'/city/' + row.original.cityId}>{row.value}</a>
                </Typography>
            )
        },
        {
            Header  : <Typography>State</Typography>,
            accessor: 'stateName',
            id      : 'State'
        }
    ]}
    onFetchData={this.fetchData}
    data={this.state.grid.data}
    pages={this.state.grid.pages}
    loading={this.state.grid.loading}
    defaultPageSize={10}
    className='-striped -highlight'
/>


Another nice thing when related properties are grouped together, it makes the code shorter and idiomatic when used with spread operator:

<ReactTable
    manual={true}
    columns={[
        {
            Header  : <Typography>City</Typography>,
            accessor: 'cityName',
            id      : 'City',
            Cell    : row => (
                <Typography>
                    <a href={'/city/' + row.original.cityId}>{row.value}</a>
                </Typography>
            )
        },
        {
            Header  : <Typography>State</Typography>,
            accessor: 'stateName',
            id      : 'State'
        }
    ]}
    onFetchData={this.fetchData}
    {...this.state.grid}
    defaultPageSize={10}
    className='-striped -highlight'
/>


Happy Coding!

React does not recognize the `inputRef` prop on a DOM element

With this code:
<Field
    name='locationTypeFk'
    id='locationTypeFk'
    label='Location Type'
    component={RadioGroupField}
    validate={required}
    margin='normal'
    fullWidth={true}
    required={true}
>
    {this.state.locationTypes.map(l =>
        <label key={l.id}>
            <Field
                name='locationTypeFk'
                component={RadioField}
                type='radio'
                color='primary'
                value={l.id}
            />
            <strong>{l.name}</strong>
        </label>
    )}
</Field>

I got this warning:
warning.js:33 Warning: React does not recognize the `inputRef` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `inputref` instead. If you accidentally passed it from a parent component, remove it from the DOM element.


To solve that, use <React.Fragment>, you can also use React.Fragment's shorthand, i.e., <>

<Field
    name='locationTypeFk'
    id='locationTypeFk'
    label='Location Type'
    component={RadioGroupField}
    validate={required}
    margin='normal'
    fullWidth={true}
    required={true}
>
    <>
        {this.state.locationTypes.map(l =>
            <label key={l.id}>
                <Field
                    name='locationTypeFk'
                    component={RadioField}
                    type='radio'
                    color='primary'
                    value={l.id}
                />
                <strong>{l.name}</strong>
            </label>
        )}
    </>
</Field>

React.Fragment will capture the inputRef prop instead of it being passed to label. At least that's how I understand it.


Happy Coding!

Monday, May 21, 2018

Typescript definition for process.env

// autocomplete for process.env.
declare global
{
    namespace NodeJS
    {
        // tslint:disable interface-name
        interface ProcessEnv
        {
            NODE_ENV?: 'production' | 'development';
            FACEBOOK_CLIENT_ID: string;
            FACEBOOK_CLIENT_SECRET: string;
            GOOGLE_CLIENT_ID: string;
            GOOGLE_CLIENT_SECRET: string;
            JWT_SIGNING_KEY: string;
        }
    }
}

// https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html
export {};


Happy coding!

Saturday, May 19, 2018

Redux Reducer Perfection with Immer




All of these achieves the same thing. The last one is the perfect one.

export function counterReducer(
    state: ICounterMore = {count: 0, message: 'hello'},
    action: ICounterAction
) // : ICounterMore, automatically inferred from return produce
{
    return produce(state, draft => {
        switch (action.type) {
            case CounterKind.INCREMENT:
                ++draft.count;
                break;
            case CounterKind.DECREMENT:
                --draft.count;
                draft.message = 'hey';
                break;
        }
    });
}


export const counterReducer = (
    state: ICounterMore = {count: 0, message: 'hello'},
    action: ICounterAction
) // : ICounterMore, automatically inferred from return type of produce
    => produce(state, draft =>
    {
        switch (action.type) {
            case CounterKind.INCREMENT:
                ++draft.count;
                break;
            case CounterKind.DECREMENT:
                --draft.count;
                draft.message = 'hey';
                break;
        }
    });


export const counterReducer = produce((
    draft: ICounterMore = {count: 0, message: 'hello'},
    action: ICounterAction
) // : ICounterMore, automatically inferred from return draft
=> {
    switch (action.type) {
        case CounterKind.INCREMENT:
            ++draft.count;
            break;
        case CounterKind.DECREMENT:
            --draft.count;
            draft.message = 'hey';
            break;
    }
    return draft;
});

Friday, May 18, 2018

Mutating React state

This won't work. React can't detect mutation when done this way:
interface IComponentState
{
    numberList: number[];
}

export class HomeComponent extends React.Component<ComponentProps, IComponentState>
{
    private addNumber(): void
    {
        this.state.numberList.push(Math.random());
    }
}

This works, but would have to produce immutable explicitly:
private addNumber(): void
{
    const newArray = [...this.state.numberList, Math.random()];
    this.setState({numberList: newArray});    
}


Producing immutable the convenient way, use immer:
private addNumber(): void
{
    // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-390110697

    this.setState(produce<IComponentState>(draft => {
        draft.numberList.push(Math.random());
    }));
}


Deleting an element from an array:
{this.state.numberList.map((n, i) =>
    <div key={i}>
        {n}
        <button
            // tslint:disable jsx-no-lambda
            onClick={() => {
                this.state.numberList.splice(i, 1);
            }}
        >
            Non-working delete
        </button>

        <button
            // tslint:disable jsx-no-lambda
            onClick={() => {
                this.setState({
                    numberList: [
                        ...this.state.numberList.slice(0, i),
                        ...this.state.numberList.slice(i + 1)
                    ]
                });
            }}
        >
            Delete using explicit immutable
        </button>

        <button
            // tslint:disable jsx-no-lambda
            onClick={() => {
                this.setState(produce<IComponentState>(draft => {
                    draft.numberList.splice(i, 1);
                }));
            }}
        >
            Delete the easier way
        </button>
    </div>
)}



Happy Coding!