Sometimes, you may need a component to have access to global states, reducers, or dispatchers that are not defined in the container mapStateToProps or mapDispatchToProps.

<aside> ⚠️ Some containers may not have the mapStateToProps or mapDispatchToProps functions defined for you to extend. For example, the Field container in ScandiPWA does not have them. In such cases, you can use the getStore method from the util/Store directory to access the Redux state and dispatch when extending the component.

</aside>

One option would be to override the component, but it is almost never a good idea. In most cases, it’s better to extend the component by using plugins.

This tutorial is assuming as an example that you want to make the Checkout component able to access:

To better understand this tutorial, you can read the following pages:

How to Work with Redux?

How to work with plugins?

To plugin into mapStateToProps and mapDispatchToProps you need to:

  1. Create a plugin file for the component
  2. Define the functions that will update the original mapStateToProps and mapDispatchToProps
  3. Export the object that maps the original function to the ones you want to plugin

1 - Create a plugin file for the component

ScandiPWA follows a pattern for naming plugins and determining their location. In this case, the original file that defines the mapStateToProps and mapDispatchToProps functions is called Checkout.container.js.

Therefore, create a file named Checkout.container.plugin.js in the src/plugin directory.

2 - Define the functions that will update the original mapStateToProps and mapDispatchToProps

This step involves creating the function to update the initial mapStateToProps and mapDispatchToProps. Since the original functions define its own namespace, when defining a plunging to then, it will accept as parameters the args and the callback.

The contents of args will vary depending on the original function. In mapStateToProps, it contains state, and in mapDispatchToProps, it contains dispatch. You should use these and return the new desired object.

When naming functions, use descriptive names. This will be helpful when someone needs to debug the application. This tutorial will define addChartStatesToMapStateToProps and addSizeDispatcherToMapDispatchToProps(probably could be better).

<aside> 🚨 Avoid not using the callback(...args) function, unless absolutely necessary.

</aside>

How to define a function to plugin to mapStateToProps?

The args content includes the state object that is passed to the original mapStateToProps function. You should use it to define the states that you want to have.

const addChartStatesToMapStateToProps = (args, callback) => {
    const [state] = args;

    const { SizeChartReducer: { config, chart } } = state;

    return {
        ...callback(...args),
        sizeChartConfig: config,
        sizeChart: chart
    };
};

How to define a function to plugin to mapDispatchToProps?

The args content contains the dispatch object that is passed to the original mapDispatchToProps function. You should use it to define dispatchers or functions that dispatch an action as props.

import SizeChartDispatcher from '../store/SizeChart.dispatcher';
import { resetSizeChart } from '../store/SizeChart.action';

const addSizeDispatcherToMapDispatchToProps = (args, callback) => {
    const [dispatch] = args;

    return {
        ...callback(...args),
        updateSizeChartConfig: () => SizeChartDispatcher.getSizeChartConfig(dispatch),
        resetSizeChart: () => dispatch(resetSizeChart())
    };
};

3 - Export the object that maps the original function to the ones you want to plugin

To finalize the implementation, you need to export an object that maps the original function to the function you want to plug in.

For this step is necessary to have the namespace of the original function. The namespace is defined right above the original function definition.

By studying the original ScandiPWA’s Checkout container, you’ll discover that:

<aside> ⚠️ These namespaces and functions are just examples from the tutorial. You should check the namespaces of the component you want to extend.

</aside>

export default {
    'Route/Checkout/Container/mapStateToProps': {
        function: addChartStatesToMapStateToProps
    },
    'Route/Checkout/Container/mapDispatchToProps': {
        function: addSizeDispatcherToMapDispatchToProps
    }
};

You have now successfully implemented a plugin for the mapStateToProps and mapDispatchToProps functions.