In our previous article, we explored the industry-standard approach to implementing a bottom sheet in React Native by making it a separate screen. This method enhances reusability, isolation, and scalability. Now, we’ll take it a step further by driving the menu options and actions directly from the backend, allowing for dynamic content and behavior without requiring front-end changes.
Why Drive Menus from the Backend?
By controlling the bottom sheet’s menu options and actions through the backend, you achieve several key benefits:
Flexibility: Update menu options, icons, and actions without requiring app releases. This allows for instant updates and A/B testing.
Consistency: Ensure that all users see the same options and actions, regardless of their app version.
Maintainability: Simplify the front-end code by offloading decision-making to the backend, reducing complexity and potential bugs.
How It Works
In this approach, the backend will provide an array of menu options based on a source
parameter passed from the front end. Each option will include a title, icon, and a ctaAction
that determines what action to take when the option is selected. The front-end will render these options and use a custom hook to handle the ctaAction
.
Backend API Structure
The backend API will return a JSON response with the following structure:
{
"menuOptions": [
{
"id": "1",
"title": "Profile",
"icon": "user",
"ctaAction": {
"type": "APP_NAV",
"body": {
"route": "ProfileScreen"
}
}
},
{
"id": "2",
"title": "Settings",
"icon": "settings",
"ctaAction": {
"type": "REPLACE_NAV",
"body": {
"route": "SettingsScreen"
}
}
}
]
}
Each ctaAction
object will have a type
and a body
. The type determines what action to take, and the body contains the necessary details for that action.
Front-End Implementation
Fetching Menu Options
When the bottom sheet screen is loaded, you’ll make an API call to fetch the menu options based on the
source
parameter.useEffect(() => { const { source } = route.params; fetchMenuOptions(source); }, [route.params]); const fetchMenuOptions = async (source) => { try { const response = await fetch(`https://api.example.com/menu?source=${source}`); const data = await response.json(); setMenuOptions(data.menuOptions); } catch (error) { console.error('Failed to fetch menu options', error); } };
Rendering Menu Options
Render the menu options using a
FlatList
, and attach a click handler to trigger the appropriate action.<FlatList data={menuOptions} renderItem={({ item }) => ( <TouchableOpacity onPress={() => handleMenuOptionPress(item.ctaAction)}> <View style={{ flexDirection: 'row', alignItems: 'center' }}> <Icon name={item.icon} size={24} /> <Text style={{ marginLeft: 10 }}>{item.title}</Text> </View> </TouchableOpacity> )} keyExtractor={(item) => item.id} />
Handling Actions with a Custom Hook
Create a custom hook,
useCtaActions
, to handle different types of actions. This hook will take thectaAction
object from the backend and perform the appropriate action.const useCtaActions = () => { const navigation = useNavigation(); const triggerAction = (ctaAction) => { switch (ctaAction.type) { case 'APP_NAV': navigation.navigate(ctaAction.body.route); break; case 'REPLACE_NAV': navigation.replace(ctaAction.body.route); break; case 'API_CALL': fetch(ctaAction.body.endpoint, { method: ctaAction.body.method }) .then(response => response.json()) .then(data => console.log('API Call Success:', data)) .catch(error => console.error('API Call Error:', error)); break; case 'TRIGGER_EVENT': // Implement event handling logic break; default: console.warn('Unknown action type:', ctaAction.type); } }; return { triggerAction }; };
Triggering the Action
When a menu option is selected, call the
triggerAction
function with thectaAction
object:const { triggerAction } = useCtaActions(); const handleMenuOptionPress = (ctaAction) => { triggerAction(ctaAction); };
Conclusion
By driving the bottom sheet menu options and actions from the backend, you gain significant flexibility and control over your app’s UI and behavior. This approach allows for rapid updates, ensures consistency, and reduces the complexity of your front-end code.
The key to this system is the ctaAction
structure, which decouples the UI logic from the business logic, making your app more maintainable and scalable.
This is the real backend driven menu system which is being applied industry wide now. Stay tuned for more articles!!