Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Create a redux-connected custom widget

Describes how to create a Redux-connected widget.

This example shows how to create a more complex widget in Spire.

  • This widget is connected to Redux.
  • This widget displays a list of the languages configured for the current site.
  • The widget does NOT have CMS field definitions.

📘

Prerequisites

You have created a custom blueprint.

Create the widget in code

  1. Open your IDE.

  2. In your IDE, open the \~/src/FrontEnd directory from your
    InsiteCommerce project repository.

  3. In the \~/src/FrontEnd/modules/{BlueprintName}/src/Widgets
    directory, create a new file named ReduxConnectedWidget.tsx.

  4. Add the following code to the _ReduxConnectedWidget.tsx _file.

    import{ connect }from"react-redux";
    import{ getLanguages }from"@insite/client-framework/Store/Context/ContextSelectors";
    importApplicationStatefrom"@insite/client-framework/Store/ApplicationState";
    importReactfrom"react";
    import siteMessage from"@insite/client-ramework/SiteMessage";
    importTypographyfrom"@insite/mobius/Typography";
    importWidgetModulefrom"@insite/client-framework/Types/WidgetModule";
    
    // The `ApplicationState` type represents the entire Redux store
    // for the Spire Storefront.
    
    constmapStateToProps=(state:ApplicationState)=>(
      {
        // Selectors are provided to access parts of the Redux store
        // more easily. If a selector is available to access the part of
        // the store you need, you should use the selector instead of
        // navigating the store manually.
    
        languages:getLanguages(state),
      }
    );
    
    typeProps=ReturnType<typeof mapStateToProps>;
    
    constReduxConnectedWidget=(props:Props)=>{
      if(!props.languages|| props.languages.length===0){
        return(
     // For longer text strings that are displayed to the user,
     // you should use site messages. The `siteMessage` function
     // will retrieve the site message configured in the Admin Console.
     <Typography>{siteMessage("This site has no languages configured.")}</Typography>
        );
      }
      return(
        <ul>{props.languages.map(lang=>(
     <li key={lang.id}>{
       /* Whenever you display text, you should try to do so
     using a Mobius component. This will ensure that the
     styles from the Mobius theme are used.
       */
     }
       <Typography>{lang.description}</Typography>
     </li>
        ))}
        </ul>
      );
    };
    
    const widgetModule:WidgetModule={
      component:connect(mapStateToProps)(ReduxConnectedWidget),
      definition:{
        fieldDefinitions:[],
        group:"Common",
      },
    };
    
    exportdefault widgetModule;
    
    import{ connect }from"react-redux";
    import{ getLanguages }from"@insite/client-framework/Store/Context/ContextSelectors";
    importApplicationStatefrom"@insite/client-framework/Store/ApplicationState";
    importReactfrom"react";
    import siteMessage from"@insite/client-ramework/SiteMessage";
    importTypographyfrom"@insite/mobius/Typography";
    importWidgetModulefrom"@insite/client-framework/Types/WidgetModule";
    
    // The `ApplicationState` type represents the entire Redux store
    // for the Spire Storefront.
    
    constmapStateToProps=(state:ApplicationState)=>(
      {
        // Selectors are provided to access parts of the Redux store
        // more easily. If a selector is available to access the part of
        // the store you need, you should use the selector instead of
        // navigating the store manually.
    
        languages:getLanguages(state),
      }
    );
    
    typeProps=ReturnType<typeof mapStateToProps>;
    
    constReduxConnectedWidget=(props:Props)=>{
      if(!props.languages|| props.languages.length===0){
        return(
     // For longer text strings that are displayed to the user,
     // you should use site messages. The `siteMessage` function
     // will retrieve the site message configured in the Admin Console.
    
     <Typography>{siteMessage("This site has no languages configured.")}</Typography>
        );
      }
    
      return(
        <ul>{props.languages.map(lang=>(
     <li key={lang.id}>{
       /* Whenever you display text, you should try to do so
     using a Mobius component. This will ensure that the
     styles from the Mobius theme are used.
       */
     }
       <Typography>{lang.description}</Typography>
     </li>
        ))}
        </ul>
        );
      };
    
    const widgetModule:WidgetModule={
      component:connect(mapStateToProps)(ReduxConnectedWidget),
      definition:{
        fieldDefinitions:[],
        group:"Common",
      },
    };
    
    exportdefault widgetModule;
    

    Take a closer look at the code.

    // The `ApplicationState` type represents the entire Redux store
      // for the Spire Storefront.
    
      constmapStateToProps=(state:ApplicationState)=>(
        {
          // Selectors are provided to access parts of the Redux store
          // more easily. If a selector is available to access the part of
          // the store you need, you should use the selector instead of
          // navigating the store manually.
    
          languages:getLanguages(state),
        }
      );
    
      // The `ApplicationState` type represents the entire Redux store
      // for the Spire Storefront.
    
      constmapStateToProps=(state:ApplicationState)=>(
        {
          // Selectors are provided to access parts of the Redux store
          // more easily. If a selector is available to access the part of
          // the store you need, you should use the selector instead of
          // navigating the store manually.
    
          languages:getLanguages(state),
        }
      );
    

    This is the standard mapStateToProps function used by react-redux. The type ApplicationState is the entire redux state in Spire. The getLanguages function is a selector. The selector knows how to find the languages data in the redux state. Spire provides selectors for some parts of the state. It is recommended to use them when possible. This helps keep the component unaware of where data is stored in the state. The creators of React Redux recommend using selectors to access parts of the state (Use Selector Functions to Extract and Transform data).

    The selectors in Spire can be found in the ~\modules\client-framework\src\Store directory. The subdirectories are named the same as the properties in the ApplicationState object. Selectors can be found in files named *Selectors.ts.

    This is the location of the getLanguages selector used in this widget.

    type Props = WidgetProps & ReturnType<typeof mapStateToProps>;
         const ReduxConnectedWidget = (props: Props) => {
    

    The Props type is a union of two types. ReturnType builds a type for function's return type (Return Type).

    const widgetModule: WidgetModule = {
        component: connect(mapStateToProps)(ReduxConnectedWidget),
        definition: {
          fieldDefinitions: [],
          group: "Common",
        },
      };
    

    The WidgetModule has a required property named component. When you connect a component to Redux, you can assign the result of executing connect()(ComponentName) to this component property. This gives access to the component so Spire can render it where it is needed.
    export default widgetModule;
    Remember that the default export for a widget file MUST be the WidgetModule object.

  5. Save the file.

  6. Run Spire using your custom blueprint. Below shows how to start Spire from the terminal.
    npm run start myCustomBlueprint 3000

    📘

    Note

    The Spire source code includes launch configurations for VS Code. You can also start Spire within VS Code.

Add the widget to the home page

  1. Go to the CMS in a browser. The URL is http://localhost:3000/contentadmin. Change the port number if you
    start Spire with a different port number argument.

  2. Click the Home Page link in the left navigation.

  3. Click the edit icon at the top right to edit the page.

  4. Click the plus icon at the bottom of the page to add a row.

  5. Click the plus icon within the row to add a widget.

  6. Click the Redux Connected Widget in the Add Widget modal.

  7. Click the Publish button to publish the changes to the Storefront.