17

I am using lightning:navigation component in our project, and it doesnt refresh the state of component, when the url changes. To be clear, lightning framework just keeps the state of component/page and ignores url changes, even when we go through different records, page layouts etc.

I think its a bug, i opened a case, but we are just signed partners and dont have proper service support, even if we inform SF about a bug, this is sad :(

So here is the scenario. We have action button on opportunity. When we click on it, it fires a method on ActionLauncher component, which redirects us from Opportunity Detail Page to our Container component. The url includes opportunity id, which we use in Container component to get some data from backend(apex).

ActionLauncher component:

<lightning:navigation aura:id="navigation"/>

ActionLauncher controller:

navigateToContainer : function(component, event) {
   var componentName = "Container";
   var recordId = component.get("v.recordId");
   var attributes = {"id": recordId};

   component.find("navigation")
    .navigate({
        "type": "standard__component",
        "attributes": {
            "componentName": componentName
        },
        "state" : attributes
    });
},

Container component:

<aura:component description="Container" implements="lightning:isUrlAddressable">

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

Container controller:

doInit : function(component, event, helper) {
   var pageReference = component.get("v.pageReference");

   if (pageReference) {
       var opportunityId = pageReference.state("id");
       component.set('v.recordId', opportunityId);

       //get some data from backend
   }
},

How I test it. I go to opportunity 1. Click action button -> In ActionLauncher we input opportunityId to url -> Container component invoke doInit and grabs opportunityId url, get data from backend.

Then i go back to Opportunity 1 Detail Page -> to All Opportunities -> select Opportunity 2 -> click action button. And now with another opportunityId -> ActionLauncher -> Container

And here we have new url with opportunity 2 Id, but container does not refresh the state, it keeps old state of opportunity 1 Id.

doInit of Container doesnt run again and i cannot use any events to fire it again, as we redirected to another page and our ActionLauncher belongs to Opportunity detail page.

And there is no proper way to inform Container component about changes in url.

IMHO when we use standard lightning navigation like that, lightning framework should always refresh components and run doInit method, if its there, I count this as a bug.

If I am wrong guys, just give me an example how to handle this situation :).

Meanwhile i am using a dirty solution, which helps me to sync Container content with url.

I added refreshData method to Container component, which invokes every second and checks the url opportunity id if it matches component opportunity id.

I dont like this solution, but i couldnt find anything better.

refreshData : function(component, event) {
    var pageReference = component.get("v.pageReference");

    if (pageReference) {
        var urlOpportunityId = pageReference.state("id");
        var componentOpportunityId = component.get('v.recordId');

        if (urlOpportunityId && urlOpportunityId != componentOpportunityId) {
            console.log("refreshData, run container doInit");
            this.doInit(component, event);
        }
    }

    setTimeout($A.getCallback(() => this.refreshData(component, event)), 1000);
},
  • I understand your issue, and while I think the addition of a useCache:false would be a welcome addition to lightning:navigation, I am pretty the decision to not re-init is by design. Curious, if you fire an Application Event before navigation, does the Container handle the listen? – tsalb Jul 12 '18 at 20:07
  • i tried to use application event, didnt work for me. I will check useCache:false – Bogdan K Jul 13 '18 at 6:38
  • Oops, that's not a real attribute, I just meant that it would be nice if that WERE one. The app event didn't work... What if you tried destroying your Container when you navigate away from it? – tsalb Jul 13 '18 at 7:13
  • haha, i started to google, thought, that i missed some standard lt functionality :D – Bogdan K Jul 13 '18 at 7:20
  • 1
    Actually, this event might help: developer.salesforce.com/docs/component-library/bundle/… – tsalb Jul 13 '18 at 7:31
21

We're running into this too. We expected it to be the case that if we navigate to a Lightning Component URL once, then walk through other pages, then navigate back to it with a different URL, we'll get a brand new instance and see the init method fire. Instead we get a stale older version with no init fired. So it's not clear what to do if what we really want is that new instance.

Will post back here if we find out exactly the best way to work around it.

EDIT: Aha! I found a relevant approach.

In the component with lightning:isUrlAddressable simply add a change handler for the pageReference state.

<aura:handler name="change" value="{!v.pageReference}" action="{!c.reInit}" />

And then your reInit method can reset the component back to whatever it needs to be. If you need more fine-grained logic (only reset it if a specific parameter changed, etc) then your reInit method can compare values as needed to produce the desired logic.

As far as I can tell in brief testing, the change handler does not fire on initial load (use your usual init method for that), nor on being reached via back/forward button. It fires on re-navigation to the component (even if the state parameters passed are identical) and it fires if the component internally uses lightning:navigation to change its own state.

  • This looks promising - I'll investigate. – Caspar Harmer Aug 2 '18 at 21:16
  • agree, your solution is more elegant, even though i still think, its a lightning bug :) – Bogdan K Aug 6 '18 at 14:11
  • 1
    I posted this (with link included) to the Partner Forum "Lightning and Components" group. A Salesforce SVP has already seen it and tagged someone in from the appropriate team. Will update here with any responses :) – Charles T Aug 7 '18 at 4:14
6

I found a relevant approach.

In the component with lightning:isUrlAddressable simply add a change handler for the pageReference state.

Component:

<aura:handler name="change" value="{!v.pageReference}" action="{!c.reInit}" />

Controller.js:

    reInit : function(component, event, helper) {
        $A.get('e.force:refreshView').fire();
    }
3

I have the same issue with you, aura init event is not getting fired when second time visits the same lightning component.

My workaround is firing the refresh event after navigating to the Lightning component.

navigateToMyCmp : function(component, event, helper) {
    event.preventDefault();
    var pageReference = {
        type: 'standard__component',
        attributes: {
            componentName: 'c__MyCmp',
        },
        state: {
            "recordId": component.get("v.recordId")
        }
    };
    helper.navService(component, pageReference);
    helper.delayedRefresh();
}, 

navService : function(component, pageReference, replace){
    let _replace = replace || false;
    let navService  = component.getSuper().find('navigationService');
    navService.navigate(pageReference, _replace);

},

delayedRefresh : function(milliseconds){
    let ms = milliseconds || 500;
    window.setTimeout($A.getCallback(function(){
        $A.get('e.force:refreshView').fire();
    }),ms);
},

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.