Backend-Driven Menus: Empowering Your Menu with Dynamic Options and Actions

Backend-Driven Menus: Empowering Your Menu with Dynamic Options and Actions

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:

  1. Flexibility: Update menu options, icons, and actions without requiring app releases. This allows for instant updates and A/B testing.

  2. Consistency: Ensure that all users see the same options and actions, regardless of their app version.

  3. 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

  1. 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);
       }
     };
    
  2. 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}
     />
    
  3. Handling Actions with a Custom Hook

    Create a custom hook, useCtaActions, to handle different types of actions. This hook will take the ctaAction 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 };
     };
    
  4. Triggering the Action

    When a menu option is selected, call the triggerAction function with the ctaAction 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!!

Did you find this article valuable?

Support Dev Tools by becoming a sponsor. Any amount is appreciated!