Methods
# addEpic(name, epic)
It adds a new epic to the root epic. Note: The new epic will replace the old epic if “name” used to add an epic already exists.
Parameters:
Name | Type | Description |
---|---|---|
name |
String | Epic name |
epic |
Epic |
Example
...
import { asObservable } from "@src/epics/rxUtils";
const { getApi } = require("@src/services");
import { errorToAction } from "@src/utils";
export const applyCustomCode = externalCodeSetup => {
const courseRemoveFail = (error) => ({
type: "COURSE_REMOVE_ERROR",
error,
})
const courseRemoveItem = (
action$,
store
) =>
action$
.filter(
a =>
a.type === "COURSE_REMOVE_ITEM" //Observer for type "COURSE_REMOVE_ITEM". If called, proceed with mergeMap function
)
.mergeMap(a => {
let state = store.getState();
let { config } = state;
//Create a "loading" observable
const loadingObservable = Observable.of({
type: "COURSE_REMOVE_LOADING"
});
const api = getApi(config);
const urlPath = "https://api-to-call.com",
method = "GET",
paramsOrPayload = {},
validation = {},
isfullUrl = true,
headers = {
appid: config.app_id
}
//Use BuddyBoss helper function "api.customRequest"
const apiToCall = api
.customRequest(
urlPath,
method,
paramsOrPayload,
validation,
headers,
isfullUrl
);
const requestObservable = asObservable(apiToCall)
.map(() => ({
type: "COURSE_REMOVE_SUCCESS"
}))
.catch(ex =>
Observable.of(
errorToAction(ex, e =>
courseRemoveFail(e)
)));
return Observable.concat(loadingObservable, requestObservable);
});
externalCodeSetup.reduxApi.addEpic("courseRemoveItem", courseRemoveItem);
}
# addMiddleware(middleware)
You can use it to add a new middleware to store initialization
Parameters:
Name | Type | Description |
---|---|---|
middleware |
ReduxMiddleware |
Example
import thunk from 'redux-thunk';
...
externalCodeSetup.reduxApi.addMiddleware(thunk)
# addOnStoreCreateListener(onCreated) → {function}
It can be used to execute a function once a redux store has been created.
Parameters:
Name | Type | Description |
---|---|---|
onCreated |
function | The function which will be called when redux store is created |
Unsubscribe function
Example
externalCodeSetup.reduxApi.addOnStoreCreateListener((props) => {
//Redux store has been created!
//Do something here..
})
# addPersistorConfigChanger(changer) → {Object}
You can use this to change config for redux persistor. For example, adding a new reducer to the whitelist.
Parameters:
Name | Type | Description |
---|---|---|
changer |
function | Function accepts the default persistor config; Or the changed persistor if |
PersistorConfig
Example
externalCodeSetup.reduxApi.addPersistorConfigChanger(props => {
const changedPersistor = {
...props,
whitelist: [
...props.whitelist,
"customReducer"
]
};
return changedPersistor
})
# addReducer(name, reducer)
Adds a new reducer to the root reducer. Note: If "name" used to add a reducer already exists, the new reducer will replace the old reducer.
Parameters:
Name | Type | Description |
---|---|---|
name |
String | Name of reducer |
reducer |
Reducer | Reducer function |
Example
const initialState = {
loading: false,
loaded: false,
errorMessage: null,
foodReceived: ""
}
const delivery = (state = initialState, action) => {
switch (action.type) {
case "FOOD_DELIVERY_REQUEST": {
return {
...state,
loading: true,
loaded: false,
errorMessage: null
};
}
case "FOOD_DELIVERY_SUCCESS": {
return {
...state,
foodReceived: action.foodToDeliver,
loading: false,
loaded: true,
errorMessage: null
};
}
case "FOOD_DELIVERY_FAIL": {
return {
...state,
loading: false,
loaded: false,
errorMessage: action.errorMessage
};
}
default:
return state;
}
};
externalCodeSetup.reduxApi.addReducer("food", delivery)
# overidePersistorConfig(config)
You can use this to set custom persistor configuration. It will replace the default configuration persistor from the app. Persist is used to store Redux state on disk so that it can be available after reopening the app without fetching data again. You can refer to this link for more information: https://github.com/rt2zz/redux-persist
Parameters:
Name | Type | Description |
---|---|---|
config |
Object | App persistor config |
Example
...
import AsyncStorage from "@react-native-community/async-storage";
export const applyCustomCode = externalCodeSetup => {
const persistConfig = {
storage: AsyncStorage, // where to store
whitelist: [ // names of reducers to store
"auth",
"activities",
"blog",
"messages",
"forums",
"menuSettings",
"user",
"sites",
"settings",
"blockData",
"blockLoadableDataCache",
"activitiesCache",
"usersCache",
"topicsCache",
"forumsCache",
"coursesCache",
"groupsCache",
"messagesCache",
"blogCache",
"socialGroups",
"members",
"localAuthentication",
"urls",
"inAppPurchases",
"singleCourse",
"emailInvites"
],
transforms: [reducerTransform, transformSerialiseImmutable],
debounce: 300,
key: "v5"
};
externalCodeSetup.reduxApi.overidePersistorConfig(persistConfig);
}
# setIsDataPersistingEnabled()
If set to false
, redux data won't be saved to disk.
Example
externalCodeSetup.reduxApi.setIsDataPersistingEnabled(false)
# wrapEpic(name, epicWrapper)
You can use it to wrap an epic with another epic. It can be used to filter action observables of existing epics.
Parameters:
Name | Type | Description |
---|---|---|
name |
AppEpic | |
epicWrapper |
EpicWrapper |
Example
const filterActionsWrapper = (originalEpic: Epic): Epic =>
(
action,
storeApi,
dependencies
) => {
const filteredInputActions =
action
.filter(
a =>
a.type === "CUSTOM_LOAD_COURSE_REQUEST"
)
return originalEpic(filteredInputActions, storeApi, dependencies);
};
externalCodeSetup.reduxApi.wrapEpic("loadCoursesOnRequest", filterActionsWrapper);
# wrapReducer(name, reducerWrapper)
Wraps original reducer with another reducer. It can be useful if you want to change original reducer behavior without replacing it.
Parameters:
Name | Type | Description |
---|---|---|
name |
AppReducers | Name of reducer to wrap |
reducerWrapper |
ReducerWrapper |
Example
//In custom_code/components/CourseItem.js
import React from 'react';
import { View, Text, TouchableOpacity, Button } from "react-native";
import { WidgetItemCourseUserConnected } from "@src/components/Widgets/WidgetItemCourseUser";
import { useDispatch } from "react-redux"
const NewWidgetItemCourseComponent = (props) => {
const { viewModel, global, colors } = props;
const dispatch = useDispatch();
return <View>
<View style={{ margin: 20, flexDirection: "row" }}>
<TouchableOpacity onPress={viewModel.onClick}>
<Text>
{viewModel.title}
</Text>
<WidgetItemCourseUserConnected
lightText={true}
global={global}
userId={viewModel.authorId}
colors={colors}
/>
</TouchableOpacity>
</View>
<View>
//Use dispatch() from react-redux to dispatch an action
<Button title="Remove from list"
onPress={() => dispatch({ type: "COURSE_REMOVE_ITEM", courseToRemove: viewModel.id })} />
</View>
</View>
}
export default NewWidgetItemCourseComponent;
//In custom_code/index.js...
...
import CourseItem from "./components/CourseItem"
export const applyCustomCode = externalCodeSetup => {
externalCodeSetup.coursesHooksApi.setWidgetItemCourseComponent(CourseItem);
const reducerName = "courses"; // "courses" reducer can access data displayed in courses list
//Initialize the custom reducer
const customReducer = reducer => (state = reducer(undefined, {}), action) => {
switch (action.type) {
case "COURSE_REMOVE_ITEM":
//Use variables below to get index of id which will be removed from the list
const removeWithIndex = state.all.ids.indexOf(action.courseToRemove);
const newIds = state.all.ids.splice(removeWithIndex, 1)
//Assign new state with "newIds"
const newState = {
...state,
all: {
...state.all,
ids: newIds
}
}
return reducer(newState, action);
default:
return reducer(state, action);
}
}
externalCodeSetup.reduxApi.wrapReducer(
reducerName,
customReducer
);
}