Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):
Describe the bug
iOS Only, Android worked fine
App crashes with the following error on a rotate:
file:///node_modules/@nativescript/core/ui/layouts/grid-layout/grid-layout.js:350:51: JS ERROR TypeError: undefined is not an object (evaluating 'this.columns[measureSpec.getColumnIndex()].children')
Adding some logging before that line indicates that during the rotation; the
measureSpec.getColumnIndex() = NaN which is why this fails.
To Reproduce
I have a Vue app with a grid and a v-if and a second grid with a v-else, I believe this occurs with the v-else grid getting created. Switch it to v-show seems to have fixed it.. I use the v-if/v-show to use a different grid for landscape vs portrait.
Expected behavior
No crash. :grinning:
Additional context
Even though the Vue v-else/v-if I believe is directly causing the issue; the code here measureSpec.getColumnIndex() is obviously fragile enough that it can get into a state where it is returning a NaN; that case should not be possible, as it is used by several functions in the grid layout code, meaning other corner cases might cause the same issue.
@NathanaelA can you provide a Playground demo (or archived demo project) - I've used this one to test the conditional rendering with v-if and v-else & orientation change but the issue is not reproducible.
Hi Nick (@NickIliev) , attached is a zip version of a project that crashes on rotation with the above callstack. In fact in this test version it actually crashes on startup if you are landscape; where my real app actually works on startup but only crashes when switching orientation. So it is timing dependant.
If you replace the v-if and v-else with two v-show's everything works... So I have a method that works.
I am reporting this because I feel like this might show a potential brittle area of the code that can cause crashes if the timing is wrong...
@NathanaelA it seems that for some reason this line returns undefined which results a NaN here.
There is a easy workaround this issue - set all columns (the col property of the grid children) explicitly. For example, in your case:
<GridLayout rows="auto,auto,auto" row="0" columns="*,auto" class="header" v-if="$state.orientation==='portrait'">
<Label row="0" col="0" class="title" text="1"/>
<Label row="1" col="1" class="title" text="1a"/>
</GridLayout>
<GridLayout row="0" rows="auto,auto,auto" columns="*,75,100,100,60,60,60" v-else class="header landscape">
<Label row="0" col="0" class="title" text="2"/>
<Label row="1" col="0" class="title leftMargin" text="2a" />
<Label row="2" col="0" class="title leftMargin" text="2b" />
</GridLayout>
@NickIliev - thanks; I'm already using a v-show instead of v-if which works as just as well as a work around. I'm good on that...
The only reason to bring this issue up is that it shows a case where measureSpec.getColumnIndex() returns NaN all the time.
Which in my opinion means their is something that should be eventually fixed as measureSpec.getColumnIndex() is used in a LOT of places in the grid code; and that means their could be other corner cases that could cause a grid to crash.
Most helpful comment
@NickIliev - thanks; I'm already using a
v-showinstead ofv-ifwhich works as just as well as a work around. I'm good on that...The only reason to bring this issue up is that it shows a case where
measureSpec.getColumnIndex()returnsNaNall the time.Which in my opinion means their is something that should be eventually fixed as
measureSpec.getColumnIndex()is used in a LOT of places in the grid code; and that means their could be other corner cases that could cause a grid to crash.