Redux Actions and Selectors
Introduction
React POS keeps all of its runtime data in a single Redux store. When you build a prompt in a customer project you will need to read data out of that store (the prompt's data, the values the user has typed, the POS terminal, the current resolution) and write to it (send an event back to the process, show the keyboard, update the basket view).
This document is a reference for the two things you use to do that:
- Selectors - functions that read a value out of the store.
- Actions - functions you dispatch to change the store or to send something to the server.
Only two of the Enactor packages declare actions and selectors:
| Package | Owns | Namespace in the store |
|---|---|---|
@enactor/redux-javascript-bridge | Everything that talks to the Enactor server - prompts, view data, events, messages, expressions | state.enactorBridge |
@enactor/react-base-components | Local UI state - form inputs, keyboard, basket view, resolution, notifications | state.enactorPos |
@enactor/react-pos, @enactor/self-checkout, @enactor/react-crm and @enactor/react-inventory do not declare their own actions or selectors. They only compose these two. So whenever you need a selector or an action, it comes from one of the two packages above.
If you are new to how a prompt connects to the store, read the Using Redux Store tutorial first. It walks through connect, defaultMapStateToProps and sendEvent step by step. This document is the lookup reference you come back to afterwards.
For the base components that consume this data (ConnectedTextInput, SaleShellContainer, MenuContainer and so on), see How to Customize React POS.
The store at a glance
The store has exactly two top-level namespaces. Every selector reads from one of them.
state.enactorBridge - server data
| Slice | What it holds |
|---|---|
prompts | The prompts currently open, keyed by promptInstanceId. This is where promptData lives. |
viewData | Server view data by name - POS terminal, location, base currency, attributes |
status | Bridge connection status |
config | Connection config and locale |
messages | Loaded message bases (translations) |
expressions | Cache of resolved expressions |
resources | Cache of resolved resources (images, message files) |
menus | Menu state per prompt instance |
history | Previously displayed prompts |
translations | Translation-mode groups |
stylesheetData | Server-driven stylesheets |
attachments | Captured and previewed attachments |
deviceSupport | Per-prompt device (scanner) configuration |
connections | Cache of outbound connection requests |
remoteRoutes, remoteComponentMaps, uiExtensions | UI extension (module federation) data |
configScreen, viewEvents, uiRecorder | Config overlay, registered view events, UI recorder |
state.enactorPos - local UI state
| Slice | What it holds |
|---|---|
inputs | The value cache - every value the user has typed, per prompt, plus focus and cursor state |
promptUIState | Basket items, scroll position, selected index, keyboard/keypad visibility |
keyboard | Keyboard type, default input mode, layouts |
resolution | Current device breakpoint (deviceType) |
background | Active background variant |
userNotifications, posNotifications, userTaskCount | Notification lists and task count |
transactionProcessingStatusValue | Endpoint / transaction processing status |
autoAdvance | Auto-advance index and active flag |
debug | Debug panel visibility |
You can see this whole tree live in the browser using the Redux DevTools extension. Navigate to enactorBridge -> prompts -> pagesMap -> <PageID> -> pageResponse to find the current prompt's data.
Quick start - the standard prompt pattern
Most prompts never need to reach for an individual selector. defaultMapStateToProps and defaultMapDispatchToProps already give you the standard set, and you only add selectors on top when you need something extra.
import { connect } from "react-redux";
import {
defaultMapStateToProps,
defaultMapDispatchToProps,
getValueCache
} from "@enactor/react-base-components";
import { getPageState } from "@enactor/redux-javascript-bridge";
const mapStateToProps = (state, ownProps) => {
const { promptUrl } = getPageState(state, ownProps);
return {
...defaultMapStateToProps(state, ownProps), // promptData, promptUrl, processId,
// promptInstanceId, promptTimeout, locale
valueCache: getValueCache(state, promptUrl) // the values the user has typed
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
return {
...defaultMapDispatchToProps(dispatch, ownProps) // gives you eventHandlers.sendEvent
};
};
export default connect(mapStateToProps, mapDispatchToProps)(MyPrompt);
Inside the component:
const MyPrompt = props => {
const { promptData, valueCache, eventHandlers } = props;
const handleOK = () => {
eventHandlers.sendEvent("OKPressed", { customerId: valueCache.customerId });
};
return <>{/* ... */}</>;
};
Selectors reference
All selectors take the whole store state as their first argument, unless a note says otherwise.
Prompt and page
Import from @enactor/redux-javascript-bridge.
These are the selectors you will use most. getPageState is the one nearly every prompt uses.
| Selector | Arguments | Returns |
|---|---|---|
getPageState | (state, ownProps) | A flat object: { ...ownProps, windowType, processId, promptUrl, promptData, promptInstanceId }. The standard shape for mapStateToProps. |
getPromptState | (state, ownProps) | The full page object for ownProps.promptInstanceId. Falls back to the topmost prompt if no id is given, and to a history entry if the prompt has already closed. |
getDefaultPageState | (state) | The first page in the store. Use when you have no ownProps to work with. |
selectPages | (state) | Array of all currently open pages. |
selectPagesMap | (state) | The same pages as an object keyed by promptInstanceId. |
selectPage | (state, promptInstanceId) | One page. With no id, returns the topmost (last) page. |
selectPageByPromptUrl | (state, promptUrl) | The first open page matching that prompt URL. |
selectActivePromptIds | (state) | Array of the active promptInstanceId values. |
selectControllerInstanceId | (state) | The promptInstanceId of the prompt currently driving the process. |
const { promptUrl, promptData, processId } = getPageState(state, ownProps);
Prefer getPageState over reading state.enactorBridge.prompts directly. When several prompts are open at once (a modal over a base prompt, for example), getPageState resolves the right one from ownProps.promptInstanceId for you.
Form inputs and the value cache
Import from @enactor/react-base-components.
Everything the user types into a ConnectedTextInput, ConnectedSelectInput or ConnectedCheckboxInput lands in the value cache, keyed by prompt URL and then by input name.
| Selector | Arguments | Returns |
|---|---|---|
getValueCache | (state, promptUrl) | Flat { inputName: value } for the prompt. This is what you send back to the process. |
getDisplayValueFromValueCache | (state, promptUrl) | Flat { inputName: displayValue } - the formatted text as shown on screen. |
getInput | (state, promptUrl, inputName) | The full value container for one input: value, display value, cursor position, formatter, disabled flag. |
getDefaultValueFromValueCache | (state, promptUrl) | The raw value-container map for the prompt. |
getInputsForPromptUrl | (state, promptUrl) | The whole inputs slice with its value cache narrowed to one prompt. Useful when a component needs focus and cursor state too. |
getFocussedValue | (state) | The value container of the input that currently has focus, or {}. |
getPromptInputName | (state) | The name of the prompt's implicit single input. |
const valueCache = getValueCache(state, promptUrl);
const { forename, surname, excluded } = valueCache;
value is the raw value you send to the server. displayValue is the formatted version the user sees (for example 12/05/24 for a date input, or £15.00 for a currency input). Always send value, never displayValue.
POS terminal, location and view data
Import from @enactor/redux-javascript-bridge.
View data is data the server publishes by name, independently of any prompt. It survives across prompts, so it is where terminal- and store-level information lives.
| Selector | Arguments | Returns |
|---|---|---|
getViewDataItem | (state, dataName) | Any view data item by name. The general-purpose accessor. |
getViewData | (state) | The whole viewData slice. |
posTerminalSelector | (state) | The POS terminal record. |
locationSelector | (state) | The location (store) record. |
baseCurrencySelector | (state) | The base currency. |
getPosTerminalCurrencyFromViewData | (state) | The terminal's currency ID as a string, "" if not set. |
getLocationCurrencyFromViewData | (state) | The location's currency ID as a string, "" if not set. |
getPosTerminalScannerPrefixFromViewData | (state) | The keyboard-wedge scanner address, or null. |
selectPosTerminalAttributes | (state) | The terminal attribute map. |
selectPosTerminalAttribute | (state, name, defaultValue) | One terminal attribute, or defaultValue. |
selectLocationAttributes | (state) | The location attribute map. |
selectLocationAttribute | (state, name, defaultValue) | One location attribute, or defaultValue. |
selectIsScoInPosMode | (state) | true when Self Checkout is in operator (POS) mode. Drives operator vs customer view. |
selectPosInCustomerView | (pages) | true when the POS is showing the customer view. Takes the pages array, not state - pass selectPages(state). |
// Prefer the specific selector when one exists
const currencyId = getPosTerminalCurrencyFromViewData(state);
// Fall back to the generic accessor for anything else
const myData = getViewDataItem(state, "enactor.pos.someCustomViewData");
View data has to be requested before it appears in the store. If a selector returns undefined, dispatch the matching fetch... action first - see Fetching view data.
selectPosTerminalAttribute and selectLocationAttribute return defaultValue for any falsy stored value, including 0, "" and false. If you store numeric or boolean attributes, read the whole map with selectPosTerminalAttributes / selectLocationAttributes and check the key yourself.
UI state - keyboard, resolution, basket
Import from @enactor/react-base-components.
| Selector | Arguments | Returns |
|---|---|---|
getCurrentDeviceResolution | (state) | The current breakpoint. Compare against the exported MOBILE_DEVICE, TAB_DEVICE, DESKTOP_DEVICE constants. |
getResolution | (state) | The whole resolution slice. |
getIsKeyboardVisible | (state) | true when the on-screen keyboard is showing. |
getKeyboardType | (state) | The active keyboard variant (alpha / caps / shift). |
getDefaultInputMode | (state) | Native keyboard vs application keyboard. |
getKeyboardLayouts | (state) | The configured keyboard layouts. |
getPromptUIState | (state) | Basket items, scroll position, selected index and device visibility together. |
getPreviousBasketItems | (state) | The basket as it was before the last update - use it to diff for line-add animation. |
getAutoAdvanceDetails | (state) | The auto-advance index and active flag. |
getCurrentBackground | (state) | The active background variant. |
getBridgeLocale | (state) | The locale as a string such as "en-GB", or undefined if not yet resolved. |
import { getCurrentDeviceResolution, MOBILE_DEVICE } from "@enactor/react-base-components";
const isMobile = getCurrentDeviceResolution(state) === MOBILE_DEVICE;
Notifications and task count
Import from @enactor/react-base-components.
| Selector | Arguments | Returns |
|---|---|---|
selectUserNotifications | (state) | All user notifications. |
selectUnacknowledgedUserNotifications | (state) | Only notifications whose status is not ACKNOWLEDGED. |
selectPosNotifications | (state) | POS notification messages. |
selectEndPointStatusNotifications | (state) | Endpoint / transaction processing status. |
selectUserTaskCount | (state) | The outstanding user task count. |
selectUnacknowledgedUserNotifications filters on every call, so it returns a new array each time. Used directly in mapStateToProps it will re-render the component on every dispatch. If that matters, select the full list and filter inside the component with useMemo.
Messages, expressions and resources
Import from @enactor/redux-javascript-bridge.
In most cases you should use the ResolvableMessage and Image components instead of these selectors - they handle the fetch and the caching for you. Reach for the selectors only when you need the resolved value in logic rather than in JSX.
| Selector | Arguments | Returns |
|---|---|---|
messageSelector | (state, messageBase, messageId) | One translated message string. |
expressionResultSelector | (state, expression, expressionData) | The cached result of a resolved expression. expressionData defaults to "Default". |
memoizedExpressionResultSelector | (state, expression, expressionData) | The same lookup, memoized. Prefer this one in mapStateToProps. |
getResource | (state, resourceURI) | A resolved resource entry with its content and status. |
createResourceKey | (resourceURI) | Builds the cache key used by getResource. |
stylesheetDataSelector | (state, dataName) | One resolved server-driven stylesheet. |
styleSheetLoadingSelector | (state, dataName) | Whether stylesheets are still loading. |
styleSheetLoadingSelector returns a single global loading flag - the dataName argument is accepted but does not narrow the result. Treat it as "are any stylesheets still loading".
Menus and history
Import from @enactor/redux-javascript-bridge.
| Selector | Arguments | Returns |
|---|---|---|
selectMenuState | (state) | Menu state for every prompt instance. |
selectMenu | (state, promptInstanceId) | Menu state for one prompt instance. |
selectHistoryEntries | (state) | Previously displayed prompts, oldest first. |
selectHistoryEntriesCount | (state) | How many history entries there are. |
selectHistoryEntry | (state, promptInstanceId) | One archived prompt. |
MenuContainer reads menu state for you. Use these selectors only when you are building custom menu chrome - for example a breadcrumb showing the current folder path.
Config, devices and connections
Import from @enactor/redux-javascript-bridge.
| Selector | Arguments | Returns |
|---|---|---|
getEnactorConfig | (state) | The whole connection config. |
getEnactorBridgeLocale | (state) | The locale as { language, country }. |
selectDeviceSupport | (state) | Array of per-prompt device support entries. |
selectIsCameraScannerEnabledForPrompt | (state, promptUrl) | true when the prompt declares camera scanner support. |
isScannerEnabled | (state, promptUrl) | Alias of the selector above, kept for older call sites. |
selectIsCameraScannerEnabled | (state) | Currently always returns true, to match the Android and iOS behaviour. Use the per-prompt selector instead. |
connectionsSelector | (state) | The whole outbound request cache. |
connectionSelector | (state, requestId) | The response payload for one request, or {}. |
UI extensions
Import from @enactor/redux-javascript-bridge. Relevant only if you are building a federated POS extension.
| Selector | Arguments | Returns |
|---|---|---|
selectUIExtensions | (state) | Array of loaded remote extensions. |
selectUIExtensionsLoaded | (state) | true once the extension manifest has loaded. |
uiExtensionsSelector | (state) | The whole uiExtensions slice. |
selectRemoteRoutes | (state) | The federated route table. Merged over the static routes. |
selectRemoteRoutesLoaded | (state) | true once remote routes are ready. |
selectRemoteComponentMaps | (state) | The federated component maps. |
selectRemoteComponentMapsLoaded | (state) | true once remote component maps are ready. |
selectUiRecorderEnabled | (state) | true when the UI activity recorder is on. |
Nothing renders until both selectRemoteRoutesLoaded and selectRemoteComponentMapsLoaded are true. If your extension's prompts never appear, check these two first.
Container helpers
Import from @enactor/react-base-components. These are not slice selectors, but they are what most connected prompts actually call.
| Helper | Arguments | Returns |
|---|---|---|
defaultMapStateToProps | (state, ownProps) | The standard prompt props: promptData, promptUrl, processId, promptInstanceId, promptTimeout, locale. |
defaultMapDispatchToProps | (dispatch, ownProps) | The standard dispatchers, including eventHandlers.sendEvent. |
getAllPromptsData | (state) | promptData merged across every open prompt. |
getPosState | (state) | The whole enactorPos namespace. |
getCurrencyId | (state) | The terminal currency, falling back to the location currency. Use this for FormattedAmount and currency formatters. |
getMaxIndexInList | (pageState) | The last selectable index, for keyboard list navigation. |
isPaginatedList | (list) | Whether a list is paginated. |
Actions reference
Dispatch these from mapDispatchToProps (or with the useDispatch hook). Most already come wired up through defaultMapDispatchToProps, so check there before adding your own.
Sending events to the process
Import from @enactor/redux-javascript-bridge. This is how your prompt talks back to the application process.
| Action | Arguments | What it does |
|---|---|---|
sendEvent | (pageEvent, promptData, cmpProps) | The general-purpose outbound event. |
sendPageEvent | (pageEvent, promptData) | Sends a prompt-scoped PageEvent. |
sendDeviceEvent | (eventName, scannerData, target) | Sends scanner or peripheral input. eventName defaults to "ScannerData". |
sendViewEvent | (viewEventName, viewEventData) | Sends a view-level event, not tied to a prompt. |
promptDataChanged | (dataName, dataValue, promptInstanceId) | Updates a single field on an open prompt's promptData. |
setHistoryPrompt | (promptInstanceId, pageState) | Records a prompt into history. |
In practice you rarely call sendEvent directly. defaultMapDispatchToProps wraps it as eventHandlers.sendEvent(eventName, data):
const { eventHandlers: { sendEvent } } = props;
sendEvent("OKPressed", { customerId: "12345" });
The event name must match an event configured on the Prompt State in the application process.
Form inputs
Import from @enactor/react-base-components.
The Connected* input components already dispatch these for you. You only need them when building a custom input, or when setting a value programmatically.
| Action | Arguments | What it does |
|---|---|---|
sendEventWithInput | (...) | Reads the value cache and submits it as a PageEvent. The standard "user pressed Enter" path. |
sendEventWithMultipleInputs | (...) | The same, for a multi-field form submit. |
keyPressAction | ({ ... }) | Handles a key press: applies formatting, moves the cursor, may trigger auto-advance. Takes a single object argument. |
pointAction | ({ ... }) | Sets focus and caret position from a pointer event. |
formChangeAction | ({ ... }) | Records a native input change and takes focus. |
formChangeActionWithoutFocus | ({ promptUrls, name, value }) | Sets a value without stealing focus. Use this for programmatic updates. |
inputStateCleanup | ({ promptUrls, keepLastFocusElement }) | Clears the value cache for prompts that have closed. |
formatterInitialize | (promptUrl, name, formatterConfig, minimumUnitValue) | Registers an amount / date / time formatter for one field. |
setPromptInputName | (promptInputName) | Names the prompt's implicit single input. |
initiateSelection / completeSelection | () | Open and close the text-selection guard. |
To set an input value from code without disturbing the user's focus, use formChangeActionWithoutFocus. Using formChangeAction will pull focus onto that field, which is usually not what you want mid-flow.
Fetching view data
Import from @enactor/redux-javascript-bridge.
| Action | Arguments | What it does |
|---|---|---|
fetchViewData | (viewDataName) | Requests one named view datum. |
fetchViewDataSet | (viewDataNames) | Requests several at once. Prefer this over multiple single calls. |
fetchPosTerminal | () | Requests the POS terminal record. |
fetchPosTerminalAttributes | () | Requests the terminal attribute map. |
fetchLocation | () | Requests the location record. |
fetchLocationAttributes | () | Requests the location attribute map. |
fetchBaseCurrency | () | Requests the base currency. |
fetchPosMode | () | Requests the SCO POS-mode flag read by selectIsScoInPosMode. |
registerForViewData | (viewDataName) | Subscribes so the store updates whenever the server pushes that datum. |
viewDataChanged | (dataName, dataValue) | Applies an inbound view data update. Normally dispatched by the bridge, not by you. |
// Ask for what you need once, when the prompt mounts
useEffect(() => {
dispatch(fetchViewDataSet(["posTerminal", "location"]));
}, []);
fetch... requests the value once. registerForViewData keeps it up to date. If your prompt needs to react to a value changing while it is open, register for it rather than fetching it.
Expressions, resources and messages
Import from @enactor/redux-javascript-bridge.
| Action | Arguments | What it does |
|---|---|---|
resolveExpression | (expression, expressionData, lifespan) | Resolves an Enactor expression on the server and caches the result. lifespan controls how long the cache entry lives. |
clearExpression | (expression, expressionData) | Drops one cached expression result. |
resolveResource | (...) | Resolves a resource such as an image or message file, with in-flight de-duplication. |
markResourceDirty | (resourceType, resourceURI) | Forces the resource to be refetched next time it is read. |
markResourceInUse | (resourceType, resourceURI) | Pins a resource against cache eviction. |
loadMessageResource | (messageResourceId) | Loads a message base. |
clearCache | (duration) | Purges the bridge cache. Defaults to 10000 ms. |
Prefer the resolveExpression action over the older resolveExpressionPromise helper in @enactor/react-base-components - that one is marked deprecated.
UI state
Import from @enactor/react-base-components.
| Action | Arguments | What it does |
|---|---|---|
showKeyboard / hideKeyboard / toggleKeyboard | () | Show, hide or toggle the on-screen keyboard. |
showNumPad / hideNumPad / toggleNumPad | () | Show, hide or toggle the numeric keypad. |
triggerBasketUpdate | (basketItems) | Updates the basket view. Keeps the previous list so the UI can animate new lines. |
triggerBasketScrollUpdate | (basketScrollPosition) | Updates the basket scroll position. |
triggerSelectedIndexUpdate | (selectedIndex) | Updates the selected row in a selection prompt. |
triggerAutoAdvance | (updatedIndex) | Moves focus to the next field after a full-length entry. |
deactivateAutoAdvance | () | Turns auto-advance off. |
changeBackground | (background) | Sets the background. Use the exported DEFAULT_BACKGROUND, EMPTY_BACKGROUND, SIGN_ON_BACKGROUND, SALE_BACKGROUND constants. |
resolutionChanged | (resolution) | Updates the device breakpoint. Dispatched by the resolution listener. |
showDebug / hideDebug / toggleDebug | () | Control the debug panel. |
Keyboard configuration
Import from @enactor/react-base-components.
| Action | Arguments | What it does |
|---|---|---|
changeKeyboardType | (keyboardType) | Switches the keyboard variant (alpha, caps, shift). |
changeDefaultInputMode | (defaultInputMode) | Sets the default input mode. |
useNativeKeyboard | () | Switches to the device's native keyboard. |
useApplicationKeyboard | () | Switches to the POS on-screen keyboard. |
Notifications and task count
Import from @enactor/react-base-components.
| Action | Arguments | What it does |
|---|---|---|
loadUserNotifications | () | Subscribes to user notifications. |
addUserNotifications | (userNotifications) | Sends new notifications up to the server. |
acknowledgeUserNotifications | (notificationIds) | Acknowledges notifications on the server. |
clearUserNotifications | () | Clears the local notification list. |
loadPosNotifications | () | Subscribes to POS notification messages. |
loadEndPointNotifications | () | Subscribes to endpoint status. |
loadUserTaskCount | () | Subscribes to the user task count. |
addUserNotifications and acknowledgeUserNotifications do not change the store directly - the server owns notification state, and the slice updates when the server pushes the change back. Do not expect the list to update synchronously.
Menus
Import from @enactor/react-base-components.
| Action | Arguments | What it does |
|---|---|---|
menuEvent | (menuItem, menuState, promptInstanceId) | Handles a menu button click. Folders resolve their expressions and descend, back pops a level, and buttons build event data from the value cache and submit it. |
resolveMenuExpressions | (menuFolder) | Resolves the labels and visibility of a menu folder. Returns a promise. |
MenuContainer already dispatches menuEvent for you. Call it yourself only when building fully custom menu chrome.
Config, translation, attachments and extensions
Import from @enactor/redux-javascript-bridge.
| Action | Arguments | What it does |
|---|---|---|
connectToBridge | () | Opens the WebSocket and registers all handlers. Called once by the app shell. |
updateConnectionConfig | (config) | Updates the connection config and persists it to cookies. |
updateLocale | () | Reads the locale from the bridge into the store. |
showConfigScreen / hideConfigScreen | () | Show and hide the config screen. |
showConfigOverlay / hideConfigOverlay | () | Show and hide the config overlay. |
enableDeviceSupport | (deviceSupport) | Registers per-prompt device (scanner) configuration. |
enableTranslationMode / disableTranslationMode | () | Turn translation mode on and off. |
registerTranslationGroup | (...) | Registers a translatable group. |
captureResource | (messageBase) | Opens the native attachment capture flow. |
uploadPreviewSelectedResource | () | Uploads the selected attachment to the server. |
resetAttachments | () | Clears captured attachments. |
fetchUIExtensions | () | Loads the UI extension manifest. |
setRemoteRoutes / addRemoteRoutes | (routes) | Replace or merge the federated route table. |
setRemoteComponentMaps / addRemoteComponentMaps | (componentMaps) | Replace or merge the federated component maps. |
sendCapturedEvent | (feature, scenario, events) | Ships a recorded scenario from the UI recorder. |
setUiRecorderEnabled | (enabled) | Turns the UI recorder on and off. |
Common recipes
Read the values the user has typed
import { getValueCache } from "@enactor/react-base-components";
import { getPageState } from "@enactor/redux-javascript-bridge";
const mapStateToProps = (state, ownProps) => {
const { promptUrl } = getPageState(state, ownProps);
return {
...defaultMapStateToProps(state, ownProps),
valueCache: getValueCache(state, promptUrl)
};
};
Format an amount in the terminal's currency
import { getCurrencyId, FormattedAmount } from "@enactor/react-base-components";
// in mapStateToProps
currencyId: getCurrencyId(state)
// in the component
<FormattedAmount amount={total} currencyId={props.currencyId} />
Render differently on mobile
import {
getCurrentDeviceResolution,
MOBILE_DEVICE
} from "@enactor/react-base-components";
// in mapStateToProps
isMobile: getCurrentDeviceResolution(state) === MOBILE_DEVICE
Read a terminal attribute
import { selectPosTerminalAttribute } from "@enactor/redux-javascript-bridge";
// in mapStateToProps
allowOverride: selectPosTerminalAttribute(state, "allowPriceOverride", "false")
Set an input value from code
import { formChangeActionWithoutFocus } from "@enactor/react-base-components";
const mapDispatchToProps = (dispatch, ownProps) => ({
...defaultMapDispatchToProps(dispatch, ownProps),
setInputValue: (promptUrl, name, value) =>
dispatch(formChangeActionWithoutFocus({ promptUrls: [promptUrl], name, value }))
});
Show the on-screen keyboard when a prompt opens
import { showKeyboard } from "@enactor/react-base-components";
const mapDispatchToProps = dispatch => ({
showKeyboard: () => dispatch(showKeyboard())
});
// in the component
useEffect(() => { props.showKeyboard(); }, []);
Things to watch out for
Some selector names exist twice
@enactor/react-base-components exports selectors at two levels:
- From the package root - these take the whole store state. Always import these.
- From inside individual reducer files - these take only their own slice.
getInput, getValueCache, getFocussedValue, getPromptInputName, getPromptUIState, getPreviousBasketItems, getIsKeyboardVisible, getAutoAdvanceDetails and getCurrentDeviceResolution all exist in both forms.
// Correct
import { getValueCache } from "@enactor/react-base-components";
// Wrong - this version expects the inputs slice, not the whole state,
// and will silently return undefined
import { getValueCache } from "@enactor/react-base-components/src/reducers/inputs/inputsReducer";
Passing the wrong argument does not throw - you simply get undefined. If a selector returns undefined and the data is clearly there in the DevTools tree, check your import path first.
Selectors are not memoized
There is only one memoized selector in the toolkit (memoizedExpressionResultSelector). Everything else is a plain function, and several build a new object or array on every call - getValueCache, getDisplayValueFromValueCache, getPageState and selectUnacknowledgedUserNotifications among them.
Used in mapStateToProps, a selector that returns a fresh object defeats connect's shallow comparison and the component re-renders on every dispatch. For most prompts this is harmless. If you hit a performance problem in a busy prompt such as the basket, derive the value with useMemo inside the component instead of computing it in mapStateToProps.
Two selectors take a slice, not the whole state
selectTranslationGroup and selectTransationsForPrompt (note the spelling) expect the translations slice rather than the root state. They are only relevant to translation mode.
selectPosInCustomerView takes the pages array - pass it selectPages(state).
Not everything in the source is importable
Some selectors and actions are exported from their own file but are not re-exported from the package, so you cannot import them in a customer project:
- From
@enactor/redux-javascript-bridge:viewClosed,sendViewPage,removePrompt,clearPage,resolveLocalResource,resolveResourceWithExpression,markMessageResourceDirty,enableCameraScanner,captureAttachment,previewAttachment,setPreviewButton,stylesheetDataChanged,pageUrlSelector,getMultiPromptUrls,selectHistoryMenuState,messagesSelector,viewEventsSelector,selectViewDataName - From
@enactor/react-base-components:setKeyboardLayouts,setFormValueStatus
If you need one of these, raise it rather than importing through a deep path into node_modules - deep imports break when the package is rebuilt.
getPages is an action, not a selector
Despite the get prefix, getPages() in the bridge package fetches the current page set from the bridge and dispatches an update. To read pages, use selectPages(state).
Where to look in the source
If you need something not covered here, the source is available under node_modules/@enactor in your project:
| What | Path |
|---|---|
| Bridge actions | @enactor/redux-javascript-bridge/src/actions/ |
| Bridge selectors | @enactor/redux-javascript-bridge/src/reducers/ |
| UI actions | @enactor/react-base-components/src/actions/ |
| UI selectors | @enactor/react-base-components/src/reducers/ |
| Public export list | each package's src/index.js |
There is no selectors directory - every selector lives in the reducer file that owns its slice, and each package's src/index.js is the definitive list of what you can import.
Related documentation
- How to Customize React POS - the base components that consume this data
- Using Redux Store - a step-by-step tutorial on connecting a prompt
- React Prompt Wizard - generating a new prompt component