microsoft / powerbi-client-react

Power BI for React which provides components and services to enabling developers to easily embed Power BI reports into their applications.
MIT License
310 stars 98 forks source link

"Server Error ReferenceError: self is not defined" in use the lib with typescript project #83

Closed orafaelvinicius closed 1 year ago

orafaelvinicius commented 1 year ago

I tried to use the lib in my project written in typescript, but I get the following error when I try to run it:

Server Error
ReferenceError: self is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Call Stack
Object.<anonymous>
file:///home/myProject/sistema-web-myProject/be-front/node_modules/powerbi-client-react/dist/powerbi-client-react.js (1:452)
Module._compile
internal/modules/cjs/loader.js (1085:14)
Object.Module._extensions..js
internal/modules/cjs/loader.js (1114:10)
module.load
internal/modules/cjs/loader.js (950:32)
Function.Module._load
internal/modules/cjs/loader.js (790:12)
module.require
internal/modules/cjs/loader.js (974:19)
require
internal/modules/cjs/helpers.js (101:18)
Object.powerbi-client-react
file:///home/myProject/sistema-web-myProject/be-front/.next/server/pages/dashboards/pbi.js (52:18)
__webpack_require__
file:///home/myProject/sistema-web-myProject/be-front/.next/server/webpack-runtime.js (33:42)
eval
webpack-internal:///./src/util/pbiEmbedded/pbi_getAccessToken.tsx (9:78)

What sounds strange to me is that I used pretty much the same code in another project written in javascript and everything seems to work fine.

Could you help me solve this problem and understand what is happening?

I uploaded the code to the gist if needed.

orafaelvinicius commented 1 year ago

COMPONENT CODE:

import { PowerBIEmbed } from 'powerbi-client-react';
import { models } from 'powerbi-client';

declare global {
    interface Window { report: any; }
}

export default function PbiEmbeddedDashboard() {

    return (
        <div className="App">

            <PowerBIEmbed
                embedConfig={{
                    type: 'report',   // Supported types: report, dashboard, tile, visual and qna
                    id: '<Report Id>', // the information has been filled in correctly in the project
                    embedUrl: '<Embed Url>', // the information has been filled in correctly in the project
                    accessToken: '<Access Token>', // the information has been filled in correctly in the project
                    tokenType: models.TokenType.Embed, // i also tried to use the models.TokenType.Aad but the error was the same
                    settings: {
                        panes: {
                            filters: {
                                expanded: false,
                                visible: false
                            }
                        },
                        background: models.BackgroundType.Transparent,
                    }
                }}

                eventHandlers={
                    new Map([
                        ['loaded', function () { console.log('Report loaded'); }],
                        ['rendered', function () { console.log('Report rendered'); }],
                        ['error', function (event) { console.log(event.detail); }]
                    ])
                }

                cssClassName={"report-style-class"}

                getEmbeddedComponent={(embeddedReport) => {
                    window.report = embeddedReport;
                }}
            />

        </div>
    )
};
navaneeth-rajagopalan commented 1 year ago

I have the same issue.

navaneeth-rajagopalan commented 1 year ago

Found a solution for this - the library should not be server side rendered.

try this:

const Report = dynamic(() => import('@/components/Report/Report'), { ssr: false, }) return (

  );

Here Report component uses the PowerBIEmbed component. I skip ssr on that and it works fine.

rad10wave commented 1 year ago

self is a window reference which cannot be used in server-side rendering. powerbi-client-react uses it in it's dependencies.

As a workaround you can use what @navaneeth-rajagopalan suggested.

kkd1215 commented 1 year ago

Hi there,

Thanks for reaching out! We understand that you are experiencing an error due to the absence of the window object, which is not available in server-side rendering.

We have the following 2 options to resolve this issue:

Option 1: Check if the window object exists before using it in the code. However, this approach may require to skip code that relies on the window object, which may not be ideal for our use case.

Option 2: Use dynamic imports or lazy loading to only load the code that uses the window object on the client-side. This approach ensures that the code is executed only in the browser, where the window object is available, without requiring to skip any code.

You can try the following code for using dynamic importing: import dynamic from 'next/dynamic' import { EmbedProps } from 'powerbi-client-react'; import { models } from "powerbi-client"; const PowerBIEmbed = dynamic<EmbedProps>(() => import('powerbi-client-react').then(m => m.PowerBIEmbed), { ssr: false });

Please let us know if you need any further assistance or clarification. Thank you for bringing this to our attention. We appreciate your feedback and support.

Kirbo commented 6 months ago

Hi there,

Thanks for reaching out! We understand that you are experiencing an error due to the absence of the window object, which is not available in server-side rendering.

We have the following 2 options to resolve this issue:

Option 1: Check if the window object exists before using it in the code. However, this approach may require to skip code that relies on the window object, which may not be ideal for our use case.

Option 2: Use dynamic imports or lazy loading to only load the code that uses the window object on the client-side. This approach ensures that the code is executed only in the browser, where the window object is available, without requiring to skip any code.

You can try the following code for using dynamic importing: import dynamic from 'next/dynamic' import { EmbedProps } from 'powerbi-client-react'; import { models } from "powerbi-client"; const PowerBIEmbed = dynamic<EmbedProps>(() => import('powerbi-client-react').then(m => m.PowerBIEmbed), { ssr: false });

Please let us know if you need any further assistance or clarification. Thank you for bringing this to our attention. We appreciate your feedback and support.

For me this works, if I don't use the import { models } from "powerbi-client" at all, but as soon as I add it there, I get the ReferenceError: self is not defined error again. I'd much rather define the settings e.g.:

import { Report, models } from 'powerbi-client'
...
tokenType: models.TokenType.Embed,
settings: {
    background: models.BackgroundType.Transparent,
},

...instead of this:

tokenType: 1,
settings: {
    background: 1,
},

...but my main goal now is to:

Just wanted to share my 2cents with this struggle, as I spent almost whole day dealing with this issue.