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
-
Open your IDE.
-
In your IDE, open the
\~/src/FrontEnd
directory from your
InsiteCommerce project repository. -
In the
\~/src/FrontEnd/modules/{BlueprintName}/src/Widgets
directory, create a new file named ReduxConnectedWidget.tsx. -
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 typeApplicationState
is the entire redux state in Spire. ThegetLanguages
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 namedcomponent
. When you connect a component to Redux, you can assign the result of executingconnect()(ComponentName)
to thiscomponent
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 theWidgetModule
object. -
Save the file.
-
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
-
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. -
Click the Home Page link in the left navigation.
-
Click the edit icon at the top right to edit the page.
-
Click the plus icon at the bottom of the page to add a row.
-
Click the plus icon within the row to add a widget.
-
Click the Redux Connected Widget in the Add Widget modal.
-
Click the Publish button to publish the changes to the Storefront.
Updated over 1 year ago