README
Zapp React Native Redux
This package contains the Zapp React Native Redux code.
Available reducers
all these reducers can be used by any plugin or component, by using the connectToStore
function above
styles: Available styles for the app. Color codes are fixed for React Native, and style properties are grouped in a more structured way, for more convenient use than the native side's flat map of keys.
rivers: Rivers configured for the app. Only change is the array from layout.json is changed to a map where each river is accessible with its id.
plugins: Array of plugins available in the app. No transformation is applied when this data is loaded.
pluginConfigurations:
Map of plugin configuration. For each plugin identifier, this reducer contains the plugin_configuration object coming from zapp, including the configuration_json
property, with the configuration set by zapp users.
remoteConfigurations: Custom remote configurations properties available in Zapp.
components: Map of available components for the app. No transformation is applied when this data is loaded.
appSettings: AppSettings data injected in the ZappApp component. No transformation is applied when this data is loaded.
zappPipes:
The Zapp Pipes reducer keeps track of the feed data used by the app.
A loadPipesData: (dataSourceUrl: string, clearCache: bool = false) => void
action creator is available to manually load a datasource url in the store. This function is used by the ZappPipesDataConnector decorator which automatically retrieves data from feeds for ui_components
. But it can also be used manually in plugins for instance, or in components, in order to implement features like pull-to-refresh, or automatic reload of the data...
When a datasource is retrieved through this action, it is stored in the reducer with the datasource url as key, and the returned data as value. Requesting an already fetched datasource url will skip the request, unless the clearCache
option is set to true.
Main module
The main module exports utility functions to interact with the redux store :
createZappReduxStore(config<Object>): ReduxStore
Creates the redux store Available options are :
additionalReducers<Object>
: optional map of additional reducers to configure the store. Some names are reserved and will be ignored (styles, rivers, plugins, components, appSettings, zappPipes)additionalMiddlewares<Array<ReduxMiddleware>>
: optional array of middlewares to add - by default, already includesthunk
in development envinitialState<Object>
: optional override of initialState (defaults to empty object)env<String>
: optional override to define a specific env. will automatically resolve todevelopment
|production
|test
accordingly
NB : If you experience a crash when calling this function without any option, try calling it with an empty object instead
import { createZappReduxStore, loadAppContextData, connectToStore } from "@applicaster/zapp-react-native-redux";
import fooReducer from "./reducers/Foo";
import { customMiddleware, otherCustomMiddleware } from "./middlewares/MyCustomMiddlewares";
const store = createZappReduxStore({
addedReducers: { foo: fooReducer }, // optional - map of additional reducers to add to the store
addedMiddlewares: [customMiddleware, otherCustomMiddleware], // optional - array of additional reducers - already includes thunk
initialState = {}, // optional initialState for the store,
env: __DEV__ ? "development" : "production" // optional env. Defaults to the value here, but left for testing purposes or other custom settings
});
// now let's say we want to inject styles, rivers, and a components list to the store
// this function requires access to the store's dispatch function, so it can be used only in a connected component or a middleware
const styles = { /* .. */ };
const rivers = { /* .. */ };
const components = { /* .. */ };
loadAppContextData(dispatch, { styles, rivers, components });
// and last but not least, let's create a connector function to add styles and rivers to a component
// the example below will add 3 props : styles, rivers, and a customReduxAction bound to redux's dispatcher
import UnconnectedComponent from "./components/UnconnectedComponent";
const connector = connectToStore(state => ({ styles: state.styles, rivers: state.rivers }), { customReduxAction });
const MyConnectedComponent = connector(UnconnectedComponent);
loadAppContextData(dispatch<Function>, appContextMap<Object>)
In the Redux store, context data is made of styles, rivers, plugins, components, and appSettings. The data from these reducers are read-only. Data can be replaced in the reducer by using the loadAppContextData
function declared above. When using this function, depending on the context data you are loading, a specific loader will be invoked to format the incoming data for a more convenient use in the redux store. These loaders are fairly straight forward - refer to the source code to see more details about the transformation applied.
This function loads contextual data in the redux store. multiple contexts can be loaded at once. For instance, in order to load, styles and plugins contextual data :
const styles = ...
const plugins = ...
const store = createZappReduxStore({});
loadAppContextData(store.dispatch, { styles, plugins });
This function is used when initializing the app, but can also be used later on to update the app contextual data.
connectToStore(mapDispatchToProps<Function>, actionsMap<Object>)
Returns a react-redux connector to connect a component to the store. This is simply a shorthand function that allows a simpler and shorter syntax for common patterns
import { MyComponent } from "./MyComponent";
import { connectToStore } from "@applicaster/zapp-react-native-redux";
import { pick } from "ramda";
import { fooAction } from "fooAction";
export default connectToStore(
pick(["styles", "rivers]),
{ fooAction }
)(MyComponent);
Hooks
useActions
Identical implementation, as described here: https://react-redux.js.org/api/hooks#recipe-useactions
import { useActions } from "@applicaster/zapp-react-native-redux/hooks";
const actionCreator = (payload) => {
type: "test", payload;
};
const Comp = () => {
const actions = useActions({ testAction: actionCreator });
actions.testAction("fooBar");
};
usePickFromState
Returns specified key/keys from the store.
Call signature: (keys, equalityFn) => any
keys
: key or list of keys to pick from the state. If empty, return entire redux state
equalityFn
: (prev: any, next: any) => boolean
function to compare picked data between the renders. Returning true
will stop component from re-rendering and hook will return a previous, cached result. As a default, a shallow equality check is done.
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
// redux state {foo: 'value', bar: 'value', foobar: 'value}
const Comp = () => {
const singleKey = usePickFromState("foo"); // singleKey: { foo: 'value' }
const multipleKeys = usePickFromState(["foo", "bar"]); // multipleKeys: { foo: 'value', bar: 'value' }
const noArguments = usePickFromState(); // noArguments: {foo: 'value', bar: 'value', foobar: 'value'}
};
useRedux
Hook that aims to replace connect
function providing similar functionality
Call signature: useRedux({mapStateToProps, actions, deps})
mapStateToProps
: (state) => any
state selector function that provides state in a first argument
actions
: action to be wrapped in dispatch function creators {myAction: () => {type: 'test' }}
deps
: watchers passed to useActions hook, in order to re-bind actions on a watcher change.
import { usRedux } from "@applicaster/zapp-react-native-redux/hooks";
const myAction = () => {type: 'action'}
const myAction2 = () => {type: 'action2'}
const Comp = () => {
const {state, dispatch, myAction: action, myAction2: action2} = useRedux({
mapStateToProps: state => state.foo,
actions: [{myAction2}, {myAction}],
);
};