yahoo/fluxible

dehydrated value of RouteStore contains `action` value [fluxible-router v1]

geta6 opened this issue · 5 comments

geta6 commented

When dehydrate RouteStore on server side, the value contains action of RouteStore.
I’m in troubled that transpiled code is exported to client side by server side setting.

I want the dehydrated value of RouteStore to be abstracted as before.

RouteStore

RouteStore.withStaticRoutes({
  index: {
    path: '/',
    handler: IndexComponent,
    action: async (context) => {
      await Promise.all([
        context.executeAction(FooAction, {}),
        context.executeAction(BarAction, {}),
      ]);
    },
  }
})

v0.4.x dehydrated value

{
  "RouteStore":{
    "currentUrl":"\u002F",
    "currentNavigate":{
      "transactionId":2953444313308840,
      "url":"\u002F",
      "config":{},
      },
    "currentNavigateError":null,
    "isNavigateComplete":true,
    "routes":null
  }
}

v1.0.0 dehydrated value

{
  "RouteStore":{
    "currentNavigate":{
      "transactionId":6733112344216282,
      "url":"\u002F",
      "config":{}
      "route":{
        "path":"\u002F",
        "handler":function StoreConnector(props, context) {
          React.Component.apply(this, arguments);
          this.state = this.getStateFromStores();
          this._onStoreChange = null;
          this._isMounted = false;
        },
        "action":async (context) => {
          await Promise.all([
            context.executeAction(FooAction, {}),
            context.executeAction(BarAction, {}),
          ]);
        },
        "method":"GET",
        "name":"index",
        "url":"\u002F",
        "params":{},
        "query":{}
      },
      "error":null,
      "isComplete":true
    },
    "routes":null
  }
}

Steps to reproduce the behavior

  1. Transpile javascript with different babel settings on server and client.
    - server: ['env', { targets: { node: 'current' } }]
    - client: ['env', { targets: { browsers: [...] } }]
  2. Set async function in action to create RouteStore.
  3. Embed the serialized dehydrate value in the template and render it.
  4. Open in browser that not compatible with async/await.
    - SyntaxError: Unexpected token '=>'
    - Error: `rehydrate` called with a non-object. Ensure that the parameter passed to rehydrate is a state object produced by a dehydrate call.

I think I see what's going on. In previous versions we did not dehydrate the currentRoute which contained the navigation object. Since we inverted these values in 1.0, we may need to strip out the route from currentNavigate.

Yeah, we already rehydrate the route part correctly, we just don't remove the route in https://github.com/yahoo/fluxible/blob/master/packages/fluxible-router/lib/RouteStore.js#L141

We just extended the RouteStore, overwrote the dehydrate function and stripped out the route. Has been working fine in production for weeks.

xbIm commented

@pwmckenna can you please share a code snippet for this fix?

@xbIm

class extends RouteStore.withStaticRoutes(routes) {
    dehydrate() {
        const {
            currentNavigate: {
                route,
                ...currentNavigate
            },
            ...dehydrated
        } = super.dehydrate();
        return {
            ...dehydrated,
            currentNavigate
        };
    }
}