New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

rebone

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rebone

Backbone with redux and react-like properties

  • 0.0.8
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
11
decreased by-35.29%
Maintainers
1
Weekly downloads
 
Created
Source

Setup

Rebone will need you to manually import your components (views, collections, models). In your entry point, add the following:

// Load reducers
import reducers from './reducers/combinedReducers';

// Load component files
export const requireAll = (r) => { r.keys().forEach(r); };
requireAll(require.context('./components/', true, /\.view\.js$/));
requireAll(require.context('./components/', true, /\.model\.js$/));
requireAll(require.context('./components/', true, /\.collection\.js$/));

import { Loader } from 'rebone';
Loader().init(reducers);

You may need to update the location of your component folder since the default is set to ./components

Creating a template

The system is using mustache as a templating engine, for more information please have a look at https://mustache.github.io/

<div class="component-posts" data-view="Posts" data-collection="Posts">
   
</div>

Note on data-view='Posts' and data-collection='Posts'

All views should extend ComponentView which connects to the global redux store and registers the view to receive store updates for conditional rendering and prop validation:


import { View } from 'backbone';
import { _, app, uuid } from '../index';
import $ from 'jquery';
import { store } from '../store/AppStore';
import dispatchToProps from '../store/dispatchToProps';
import { viewAcknowledge } from '../reducers/app';

export class ComponentView extends View {

    constructor (options) {
        super(options);

        // Initialize props
        this.propTypes = options.propTypes;
        this.props = options.props;

        // Assign each view a unique ID to coordinate reactive view rendering based on the redux state.
        this.uuid = uuid();

        // Subscribe to ALL store update events. For now, the views will handle filtering the actions to decide
        // if they want to render or not based on what actions have been dispatched.
        store.subscribe(this.handleStoreUpdate.bind(this));

        // If the view is instantiated sometime after the app has loaded then the state changes may be finished
        // so check if we need to go ahead with the runOnce.
        this.appLoaded();

        // Validate propTypes
        this.propTypes && this.checkProps();
    }

    /**
     * Checks if any actions were defined that need to be called via dispatch and wraps them.
     */
    handleMapDispatchToProps() {
        if (this.mapDispatchToProps) {
            this.props = { ...this.props, ...dispatchToProps(this.mapDispatchToProps) };

            // Add mapped dispatch functions to propTypes with function as type
            this.propTypes = this.propTypes ? this.propTypes : {};
            Object.keys(this.mapDispatchToProps).forEach(item => {
                this.propTypes[item] = 'function';
            });

            // Check the propTypes again since we've just added new ones
            this.checkProps();
        }
    };

    /**
     * Validate prop types if props are present.
     */
    checkProps () {
        Object.keys(this.props).map(propName => {
            const type = this.propTypes[propName];
            const propValue = this.props[propName];

            typeof propValue !== type ?
                console.warn(`${propName} requires a ${type}, instead passed ${typeof propValue}`)
                : null;
        });
    }

    /**
     * Returns an instance of the store.
     * @type {object} store
     */
    store = store;

    /**
     * Returns access to dispatch for thunks (redux actions as functions) and regular actions (objects with type property).
     * @type {function}
     */
    dispatch = store.dispatch;

    /**
     * Run onAppReady once if defined on the subclass.
     * This ensures that all collections and views have been loaded
     * and all reducers have set their initial states in the store.
     */
    appLoaded() {
        const state = store.getState();
        if (!this.loaded && state.app && state.app.loaded) {
            this.handleMapDispatchToProps();

            // Check if there is view-specific logic to execute when the store is fully loaded
            // Define onAppReady in the view to access this callback
            if (typeof this.onAppReady === 'function') {
                this.onAppReady(store);
            }
            this.loaded = true;
        }
    }

    /**
     * Returns the jQuery element of the rendered view.
     * Useful for pre-rendering a view to include as part of the render to another view.
     * @param {string} viewName
     * @param {object} options
     * @return {object} - jQuery element
     */
    renderAppView (viewName, options) {
        const { $el } = new app.views[viewName]({ ...options });

        return $el;
    }

    /**
     * Will execute each time the state is updated in the store.
     */
    handleStoreUpdate = () => {
        this.appLoaded();

        if (this.uuid) {
            const { app: { alertedListeners } } = store.getState();

            // Check if the current view needs to be notified about the store update
            if (alertedListeners.includes(this.uuid)) {
                store.dispatch(viewAcknowledge(this.uuid));

                // Execute view-specific logic (if provided) before calling render
                // Define onViewNotified in the view to access this callback
                if (typeof this.onViewNotified === 'function') {
                    this.onViewNotified();
                }

                this.render();
            }
        }

        // Check if there is view-specific logic to execute on ANY store update
        // Define onStoreUpdated in the view to access this callback
        if (typeof this.onStoreUpdated === 'function') {
            this.onStoreUpdated(store);
        }
    };

    /**
     * Sets which element in the DOM to be used as the Underscore template.
     * @param {string} templateId
     */
    setTemplate = (templateId) => {
        this.template = _.template($(`#${templateId}`).html());
    };

    /**
     * Gets an instance of a template. This usefull when you have more than just one template.
     * @param {string} templateId
     */
    getTemplateInstance = (templateId) => _.template($(`#${templateId}`).html());

    /**
     * Export underscore instance.
     */
    _ = _;

}

Example View:

import { ComponentView, app } from 'rebone';
import { fetchCollection } from '../../reducers/fetch';

require('./Posts.scss');

class Posts extends ComponentView {

    constructor(options) {
        super({
            ...options,
            events: {
                'click .post-button': 'buttonClicked'
            }
        });
    }

    onAppReady () {
        this.setTemplate('component-post');
        this.props.fetchCollection(this.collection);
    }

    buttonClicked (element) {
        const modelId = this.$(element.currentTarget).data('post-id');
        let model = this.collection.get(modelId);
        model.set({ title: 'random'});
    }

    render() {
        const { filter: { currentFilter} } = this.store.getState();
        const posts = this.collection.toJSON().filter(post => post.title.indexOf(currentFilter) > -1);
        this.$('.pure-g').html(this.template({ data: posts }));
    }

    /**
     * Define functions which need to be wrapped with dispatch.
     * @type {object}
     */
    mapDispatchToProps = {
        fetchCollection
    };
}

app.views.Posts = Posts;

Keywords

FAQs

Package last updated on 17 Jun 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc