How to combine polymer reduct and <app-route>?

We are currently using <app-route>routing and are now implementing Redux with polymer-redux. However, it is unclear what is the best way to combine the two. Since it <app-route>maintains its own state, we cannot store it in our Redux store. However, for some actions that the user can perform, we also want to update the URL.

My current line of thinking is doing something with middleware, but it’s not entirely clear to me what is the best way to access / change routes <app-route>from within this middleware. How can we best approach this?

+4
source share
2 answers

I ran into the same problem myself. The clash is that the basic principle of reduction is that it stands for a unique centralized state, while the polymer stands for several decentralized states. Matching both obviously requires some hacking from time to time. A good example is synchronizing browser URLs in redux state through a polymer (for use with a route application). Using app-location , I did the following:

<!-- my-app.html -->
<link rel="import" href="/bower_components/polymer/polymer.html">
<link rel="import" href="/bower_components/app-route/app-location.html">
<link rel="import" href="/src/redux/redux-behavior.html">
<link rel="import" href="/src/redux/route-action-creator.html">

<dom-module id="my-app">
  <template>
    <app-location route="{{_browserRoute}}"></app-location>
  </template>

  <script>
    Polymer({
      is: 'my-app',

      behaviors: [ReduxBehavior, RouteActionCreator],

      properties: {
        _browserRoute: {
          type: Object
        }
      },

      observers: [
        '_browserRouteChanged(_browserRoute.*)'
      ],

      _browserRouteChanged: function(browserRoute) {
        this.dispatch('browsed', browserRoute.base)
      }
    })
  </script>
</dom-module>
Run code

, my-app _browserRoute URL- . "" , _browserRoute.

<!-- route-action-creator.html -->
<script>
  const ROUTE_ACTIONS = {}
  const routeActions = {}

  ROUTE_ACTIONS.BROWSED = 'ROUTE_BROWSED'
  routeActions.browsed = function(route) {
    return {
      type: ROUTE_ACTIONS.BROWSED,
      route: route
    }
  }

  ROUTE_ACTIONS.REDIRECTED = 'ROUTE_REDIRECTED'
  routeActions.redirected = function(path) {
    window.history.pushState({}, null, path)
    window.dispatchEvent(new CustomEvent('location-changed'))
    return {
      type: ROUTE_ACTIONS.REDIRECTED,
      path: path
    }
  }

  /**
   * Route action creator behavior
   * @polymerBehavior
   */
  RouteActionCreator = {
    actions: routeActions
  }
</script>

<!-- route-reducer.html -->
<link rel="import" href="/src/redux/route-action-creator.html">
<script>
  const reducers = {}
  reducers.routeReducer = function(state, action) {
    if (!state) {
      return {
        current: null
      }
    }

    switch (action.type) {
      case ROUTE_ACTIONS.BROWSED:
        return Object.assign({}, state, {
          current: action.route
        })

      case ROUTE_ACTIONS.REDIRECTED:
        // Browser state is reduced in action creator because it uses an event
        return state

      default:
        return state
    }
  }
</script>

,

statePath: 'route.current'

.

this.dispatch('redirected', '/some-path')

, .

+4

, app-route, polymer-redux app-route redux.

( ):

<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/app-route/app-location.html">
<link rel="import" href="../bower_components/app-route/app-route.html">

<dom-module id="my-router">
  <style>
  </style>
  <template>
      <app-location route="{{route}}"  id="location" use-hash-as-path></app-location>
      <app-route
            active="{{active}}"
            route="{{route}}"
            pattern="/:step/:id"
            data="{{page}}"
            tail="{{tail}}">
      </app-route>
  </template>
  <script>
    (function() {
      'use strict';
      Polymer({
        is: 'my-router',
        behaviors: [ ReduxBehavior ],
        properties: {
            page: {
                type:Object,
                value: function(){ return {};},
            },
            currentAnalysisId: {
                type:String,
                statePath: 'id',
            },
            currentStep: {
                type:String,
                statePath:'currentStep',
            },
            active:{
                type: Boolean,
                observer:'_onInValidRoute'
            }
        },
        observers: [
          '_changeRoute(page)',
          '_changeStepOrAnalysisId(currentStep,currentAnalysisId)',
        ],
        actions: {
             changeStep: function(step) {
                return {
                    type: 'CHANGE_CURRENT_STEP',
                    step,
                }
            },
            loadAnalysis: function(id,step)  {
                return {
                    type: 'LOAD_ANALYSIS',
                    id,
                    step,
                }
            },
        },
        _initialized : false,
        ready: function() {
            // required otherwise if navigating to a sub-route for the first time will be reset, by the localstorage initial redux state update
            this._initialized = true;
        },
        _changeRoute: function(page) {
            // required because otherwise
            this.debounce('route_update',()=>{
                let step = page.step;
                let id = page.id;

                if (id && this.getState().id !== id) {
                        ga('send', 'event', 'Analysis', 'load');
                        this.dispatch('loadAnalysis',id,step)
                }
                else if (this.getState().currentStep !== step) {
                    this.dispatch('changeStep',step);
                }
                ga('send', 'pageview');
            },1);
        },
        _changeStepOrAnalysisId: function(step, id) {
            if (!this._initialized) {
                return;
            }
            this.debounce('state_changed',()=>{
                if (this.page.step !== step || (this.page.id !== id && this.page.id !== '' && id !== null)) {
                    this.page = {step,id};
                }
            })
        },
        _onInValidRoute: function(valid) {
            if (!valid) {
                this.async(()=> {
                    this.$.location.set('route.path','/start/');
                })
            }
        },
      });
    })();
  </script>
</dom-module>
+2

Source: https://habr.com/ru/post/1665593/


All Articles