@girders-elements/core
Version:
Girders Elements is an architectural framework that assists with building data-driven apps with React or React Native.
66 lines (54 loc) • 1.78 kB
JavaScript
import R from 'ramda'
import invariant from 'invariant'
import { warning } from '../impl/log'
import * as data from '../data'
import * as actions from '../action'
import { findParentEntry } from '../impl/cursor'
import { ActionRegistry } from '../registry'
/**
* Main application reducer.
*
* @param config A configuration object passed from the Engine component
* @param cursor The cursor representing the state.
* @param action The action.
* @returns {*} The new state represented by updated cursor.
*/
export const reducer = R.curry((config, cursor, action) => {
// skip actions that are not for us
if (!isApplicable(action)) return cursor
invariant(
cursor != null && cursor._keyPath != null,
'The reducer is meant to work only with cursors'
)
const { keyPath: fromPath } = actions.actionMeta(action)
const type = action.type
const { registry } = config
// handle global updates
if (type.startsWith('.')) {
const keyFn = el => ActionRegistry.keyFor(data.kindOf(el), type)
const entry = findParentEntry(registry, keyFn, cursor.getIn(fromPath))
if (entry != null) {
const { element, entry: update } = entry
return cursor.setIn(element._keyPath, update(element.deref(), action))
}
return cursor
}
// handle local updates
const update = registry.get(ActionRegistry.keyFromAction(action))
const element = cursor.getIn(fromPath)
if (element) {
if (update) {
return cursor.setIn(fromPath, update(element.deref(), action))
} else {
return cursor
}
} else {
warning(
'Unable to perform local update, element has changed in meantime...'
)
return cursor
}
return cursor
})
const isApplicable = R.pipe(actions.actionMeta, R.complement(R.isNil))