question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Layout is not respected when passed by props Continued

See original GitHub issue

I’m bringing up #870 again because I can’t prevent the component from setting a new layout with the current implementation.

Desired behavior

If I pass a layout as props, that layout should be what appears on the screen.

Use Case

I wish to manage the layouts on my own. When onLayoutChange fires I will handle the change with my own logic (namely, some reducer in redux), and pass the updated layout to ReactGridLayout. In some cases, the layout should not change and revert to the “current layout.”

Current behavior

Because lodash.isEqual is used to compare the previous layout’s state and the current props layout, if I pass in the “current layout” it is ignored and a new layout is put in place as if I weren’t managing it

Relevant code:

In file ReactGridLayout.jsx these lines are preventing the desired behavior:

https://github.com/STRML/react-grid-layout/blob/b4caad3af49717e2ee4d8b8dc653eef9a3a684c2/lib/ReactGridLayout.jsx#L165-L170

Proposed fix

Ideally, I would change !isEqual(nextProps.layout, prevState.propsLayout) to nextProps.layout !== prevState.propsLayout, and put the onus on the user to insure that shallow reference comparison will be enough to determine if the layout in props is actually a new layout or not. However, I can see this possibly breaking some components which recreate their layout on each render (which they probably shouldn’t be doing…).

I propose either the above change, or perhaps a flag prop on ReactGridLayout, such as managed, which would allow the user to opt-in to shallow reference comparison in the above code. For example:

      if (
        !isEqual(nextProps.layout, prevState.propsLayout) ||
        nextProps.compactType !== prevState.compactType ||
        (nextProps.managed && (nextProps.layout !== prevState.propsLayout))
      ) {

The managed prop should get a default value of false so that existing code will work as if it is not there.

If @STRML doesn’t see any major issues with this, I’ll make a PR implementing the change.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:4
  • Comments:10

github_iconTop GitHub Comments

3reactions
nathan-chappellcommented, Sep 13, 2020

@STRML Thanks for your response. I put some code together demonstrating the issue on codebox. I hope that the comments explain what is going on well enough, but the point is that, when “L1” is the selected layout, the user should not be able to change the layout. The box can drag the boxes, but when the mouse is released it should go back to its original position. When “L2” is selected, the user can change the layout as she pleased, and and when she goes to “L1” then back to “L2”, that layout is remembered.

This behavior is precisely what occurs when !isEqual(nextProps.layout, prevState.propsLayout) is changed to nextProps.layout !== prevState.propsLayout. I think it makes it even more clear when I consider a “case analysis matrix” comparing the use of isEqual to !==

comparison analysis
isEqual and === previous props are same as new props in value and reference. Props are likely intended to be an initial state, and ignored later
isEqual and !== My case. The original props and new props are same in value, but one of two things are probably true: (a) the user wishes this layout to be respected (my case), (b) the user is recreating the same props object on each render (bad practice).
!isEqual and !== A new value and object. Clearly this layout should be respected (and currently is).
!isEqual and === The value has changed, but not the reference. This means an item from the layout object was changed… This is in violation of the principle of immutable state which seems to be common in react. Note that even if you do wish to directly change state objects, you can still get !== by using a spread operator when passing the layout as props.

Basically, I don’t understand the reasoning behind using _.isEqual. It seems to disable a use case, and reference comparison seems to be more “react-y”. If there is a good reason for using _.isEqual, then I’m certainly curious. Any thoughts?

1reaction
STRMLcommented, Oct 21, 2021

I think this is a sane idea. A flag could maintain compatibility in this major version, and in a future version a HOC could do the management for the usual use case.

This could also get us on the road to the plan in #346 which is to split the transformation of the layout (compaction and conflict resolution) into interfaces that can be passed into the HOC as props or used as-needed, exported from the library. This increases the API surface area which increases the propensity for breaking changes, but it also allows new features to proceed unimpeded as plugins, outside of the RGL library. Such a design would be much, much cleaner and more flexible.

Needless to say I’m not exceptionally proud of how RGL has “organically” developed from my original needs in ~2015. It works, but it’s not particularly good at anything outside its expected use case and can’t be meaningfully extended.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Layout is not respected when passed by props Continued #1286
I'm bringing up #870 again because I can't prevent the component from setting a new layout with the current implementation.
Read more >
NextJS Typescript Layout complaining about missing props
The error messages can be quite confusing. Firstly, to pass the component page into the Layout component, you need to add an attribute...
Read more >
How to use Props in React - Robin Wieruch
As you may have noticed, props are only passed from top to bottom in React application's component hierarchy. There is no way to...
Read more >
Building a Dynamic Layout in React - YouTube
Learn how to create a re-usable list component in React that allows for rendering grid and list based data along with filtering data....
Read more >
Next.js Practical Introduction Pt. 1: Pages and Layout - Auth0
In Layout.js , use the Header and NavBar components to render any content passed through props.children within a Content container:
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found