npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-apex

v1.1.3

Published

Redux module for Salesforce Remote Actions

Downloads

412

Readme

redux-apex

npm package

Simple Redux bindings for JavaScript Remoting in Salesforce

Install

yarn add redux-apex redux-thunk

Usage

Reducer

The reducer is exported as remoteActionReducer. Selectors expect data to be located on the apex slice in state, eg:

import { combineReducers } from 'redux';
import { remoteActionReducer } from 'redux-apex';

const reducer = combineReducers({
  ...reducers,
  apex: remoteActionReducer,
});

State tree:

{
  "apex": {
    "fetchAccounts": {
      "res": [
        {
          "Id": "xxxxxxxxxx",
          "Name": "My Account"
        }
      ],
      "loading": false,
      "status": true,
      "started": 123456789,
      "completed": 123456789
    }
  }
}

Types

The package exports three action type constants. You should use these in your own reducer for loading data into your store.

import {
  REMOTE_ACTION_REQUEST,
  REMOTE_ACTION_SUCCESS,
  REMOTE_ACTION_FAILURE,
} from 'redux-apex';

Actions

Return value of action creators (to be consumed by your reducer)

type: REMOTE_ACTION_REQUEST
payload: { controller, method, params }

type: REMOTE_ACTION_SUCCESS
payload: { controller, method, params, res }

type: REMOTE_ACTION_FAILURE
payload: { controller, method, params, err }

Operations

An operation factory is exported that can be used to create a dispatchable thunk for each remote method on the backing Apex controller. The resulting operations dispatch REQUEST, SUCCESS, and FAILURE actions that are sent to the remoteActionReducer.

modules/apex/methods.js (optional)

export const FETCH_ACCOUNTS = 'fetchAccounts';
export const FETCH_CONTACTS = 'fetchContacts';
export const SAVE = 'save';

modules/apex/operations.js

const factory = createRemoteAction(ctrl);

export const fetchAccounts = factory(methods.FETCH_ACCOUNTS);
export const fetchContacts = factory(methods.FETCH_CONTACTS);
export const save = factory(methods.SAVE);

Configuration

Remote actions may be configured by passing an optional config object through either createRemoteAction, the individual factory methods, or both. Individual config will override controller's config.

modules/apex/operations.js

const factory = createRemoteAction(ctrl, { escape: false });

export const fetchAccounts = factory(methods.FETCH_ACCOUNTS);
export const fetchContacts = factory(methods.FETCH_CONTACTS, { escape: true });
export const save = factory(methods.SAVE);

For documentation on the config object, read Configuring a JavaScript Remoting Request

Development/Test Mocking

The createRemoteAction factory can take an optional function as its final argument that will intercept the remote action call. This can be used for mocking in development or test environments.

modules/apex/remoting.mock.js

const accounts = {
  '001000000000001': {
    Id: '001000000000001',
    Name: 'Foo',
  },
  '001000000000002': {
    Id: '001000000000002',
    Name: 'Bar',
  },
};

const MockController = {
  async fetchAccount(id) {
    return accounts[id];
  },
};

export default (controller, method) => (...args) => {
  const data = args.slice(0, -2);
  const [callback] = args.slice(-2, -1);

  if (!MockController[method]) {
    throw new Error(`method not implemented in mock: ${controller}.${method}`);
  }
  MockController[method](...data).then((res) => {
    callback(res, { status: true });
  });
};

modules/apex/operations.js

-const factory = createRemoteAction(ctrl);
+const factory = createRemoteAction(
+  ctrl,
+  process.env.NODE_ENV !== 'production' ? require('./remoting.mock'): null
+);

Selectors

There are a number of selector factories that can be used for accessing any piece of the apex state. Each one takes the remote action method name and returns a new selector that takes the redux state.

  • getState(state) {object} the full apex state
  • getRemoteActionState(method)(state) {object} the remote action's full state
  • getRemoteActionResult(method, defaultValue)(state) {any} the most recent return value of the remote action
  • getRemoteActionError(method)(state) {any} the most recent error of the remote action
  • getRemoteActionStatus(method)(state) {boolean} the status where false is a failure
  • getRemoteActionLoading(method)(state) {boolean} loading status
  • getRemoteActionStarted(method)(state) {integer} date in milliseconds when last called
  • getRemoteActionCompleted(method)(state) {integer} date in milliseconds when last completed

Usage by a connected component

Use the operations and selectors in your connected component:

components/App/AppContainer.js

import * as apexOperations from 'modules/apex/operations';
import * as apexSelectors from 'modules/apex/selectors';
import App from './App';

const mapState = (state) => ({
  isSaving: apexSelectors.isSaving(state),
});

const mapActions = {
  fetchAccounts: apexOperations.fetchAccounts,
  fetchContacts: apexOperations.fetchContacts,
  save: apexOperations.save,
};

export default connect(mapState, mapActions)(App);