dojo / framework

Dojo Framework. A Progressive Framework for Modern Web Apps
https://dojo.io/
Other
585 stars 78 forks source link

Dimensions meta does not invalidate when used with renderer #393

Closed aciccarello closed 4 years ago

aciccarello commented 5 years ago

Bug The invalidation from the Dimensions meta is confusing when used with a renderer function (such as the StoreProvider). When the widget is loaded, the Dimensions are never set.

Package Version: ^5.0.0

Code Code sandbox: https://codesandbox.io/embed/meta-dimenstions-with-renderer-9rt2g

class DimensionsWithRenderer extends WidgetBase {
  render() {
    const dims = this.meta(Dimensions).get("root");
    console.log('DWR: ', dims.client.height);
    return (
      <RendererWidget renderer={() => {
        const dims = this.meta(Dimensions).get("root");
        console.log('Renderer: ', dims.client.height);
        return (
          <div key="root">
          <Hello name="Dojo CodeSandbox" />
          <h2>{"Start editing to see some magic happen \u2728"}</h2>
        </div>
        );
      }} />
    );
  }
}

Expected behavior: When using the Dimensions meta, I would expect the application to re-render the renderer function when the content is initially loaded so that the Dimension value is usable (and not 0).

In the code sandbox, this would mean that either DWR: 185 or Renderer: 185 would have been logged after the widget loaded to indicate it's size.

W:  0
DWR:  0
Renderer:  0
W:  185
DWR: 185
Renderer: 185

Actual behavior:

In the code sandbox, the only way to get the dimensions is by wrapping the content of the render function into a separate widget.

W:  0
DWR:  0
Renderer:  0
W:  185
agubler commented 5 years ago

Thanks for the issue @aciccarello.

I can see how this could be confusing, however it is working as expected - metas can only work for nodes that are directly returned from a widget and not from a renderer function.

For use cases where a meta that requires access to the dom, Dimensions, Intersection, Resize etc you would need to abstract that to a separate widget and use the metas.

class MyWidget extends WidgetBase {
  render() {
    const dims = this.meta(Dimensions).get("root");
     console.log('Renderer: ', dims.client.height);
     return (
      <div key="root">
        <Hello name="Dojo CodeSandbox" />
        <h2>{"Start editing to see some magic happen \u2728"}</h2>
      </div>
    )
  }
}

class DimensionsWithRenderer extends WidgetBase {
  render() {
    return (
      <RendererWidget renderer={() => <MyWidget />} />
    );
  }
}

We will make sure this limitation is clearly documented for the new docs, cc @sbinge.

agubler commented 4 years ago

Closing as working as designed.