Improving performance with selectorsΒΆ

Example using reselect:

/// selectors.js

import { db as myDb } from './schema';
import { createSelector, createStructuredSelector } from 'reselect';

// Single table, all records, no relations
export const selectAllPosts = createSelector(
    ({ db }) => db.BlogPost,
    (table) => {
        return myDb.selectTable(table).values; // NB. should be converted to a view model.
    }
);

// using a structured selector, makes us select only the tables we want
const blogPostAndRels = createStructuredSelector({
    posts: ({ db }) => db.BlogPost,
    comments: ({ db }) => db.Comment,
    users: ({ db }) => db.User
});

// multiple complex models
export const selectAllPosts = createSelector(
    blogPostAndRels,
    (tables) => {
        // get the TableModel
        const { BlogPost } = myDb.selectTables(tables);

        return BlogPost.all().map(_serializePost);
    }
);

// single complex model by id
export const selectPost = createSelector(
    blogPostAndRels,
    (state, props) => props.postId,
    (tables, id) => {
        // get the TableModel
        const { BlogPost } = myDb.selectTables(tables);

        // get the Record by id
        const postModel = BlogPost.getOrDefault(id);

        return postModel && _serializePost(postModel);
    }
);

const _serializePost = (post) => {
    return {
        ...post.value,
        numComments: post.comments.length,
        author: post.author.value.name
    };
};

Using selectors we can improve the previous example:

import { Component } from "react";
import { connect } from "react-redux";
import { db } from "./schema";
import { selectAllPosts } from "./selectors";

class PostListComponent extends Component {
    render() {
        return <table>
            <tbody>
                {this.props.posts.map(post => (
                    <tr>
                        <td>{post.title}</td>
                        <td>{post.author}</td>
                        <td>{post.numComments}</td>
                    </tr>
                ) }
            </tbody>
        </table>;
    }
}

const mapStateToProps = (state, ownProps) => {
    return {
        posts: selectAllPosts( state )
    };
};

export const PostList = connect(mapStateToProps)(PostListComponent);