1

New to ReactTS here. Can somebody explain to me why the variable content is undefined and how to set it so I can pass its value to <App />?

It is showing undefined in both the index.tsx file and the subsequent App.tsx file.

index.tsx

import 'react-app-polyfill/ie11';
import 'react-app-polyfill/stable';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

// Declare type for drupalSettings.
declare global {
    interface Window {
        drupalSettings: {
            mydashboard: Settings;
        };
    }
}

// Declare types for the React component.
interface Elements {
    content: string[];
}

interface Settings {
    [index: string]: Elements;
}

// Get Drupal settings.
console.log('window.drupalSettings', window.drupalSettings.mydashboard) <!--- shows correct value --->

const drupalAndReactApp: Settings = window.drupalSettings.mydashboard || '';
console.log('drupalAndReactApp', drupalAndReactApp, drupalAndReactApp['test']);<!--- shows correct value --->


const { content } = drupalAndReactApp['test'];
console.log('content', content) <!--- shows undefined --->


ReactDOM.render(<App content={content} />, document.getElementById('my-app-target'));

index.tsx

    let accessToken = "";
    let embedUrl = "";
    let reportContainer: HTMLElement;
    let reportRef: React.Ref<HTMLDivElement>;
    let loading: JSX.Element;

    // eslint-disable-next-line @typescript-eslint/no-empty-interface
    interface AppProps { content: string[] };
    interface AppState { accessToken: string; embedUrl: string; error: string[]};

    class App extends React.Component<AppProps, AppState> {
    
        constructor(props: AppProps) {
            super(props);
            const { content } = props;
            this.state = { accessToken: "", embedUrl: "", error: [] };

            reportRef = React.createRef();
            console.log('props', props, content)  <!--- shows undefined --->
            // Report container
            loading = (<>
                <div id="welcome">
                    Welcome
                </div>
                <div
                   id="reportContainer"
                    ref={reportRef} >
                    Loading the report...
                </div>
            </>
        );
    }
    ...

Edit

Output of the console logs...

window.drupalSettings Object { test: "[\"authenticated\",\"administrator\"]" }

drupalAndReactApp Object { test: "[\"authenticated\",\"administrator\"]" } ["authenticated","administrator"]

content undefined

props Object { content: undefined } undefined

Edit 2

window.drupalSettings Object { content: "[\"authenticated\",\"administrator\"]" }

drupalAndReactApp Object { content: "[\"authenticated\",\"administrator\"]" } ["authenticated","administrator"]

content undefined

props Object { content: undefined } undefined

jbreslow
  • 186
  • 1
  • 11
  • 1
    Might be related: [Weird behavior with objects & console.log](https://stackoverflow.com/q/23429203) – VLAZ Feb 25 '22 at 16:50
  • 1
    Does it happen if you don't deconstruct it? Like this: `const content = drupalAndReactApp['test'];` – Alejandro Feb 25 '22 at 16:54
  • @Alejandro if I do as you suggest, then there is an error with ``. The error says, `Type 'Elements' is missing the following properties from type 'string[]': length, pop, push, concat, and 29 more.` – jbreslow Feb 25 '22 at 16:58
  • 1
    Can you show us the JSON object in `window.drupalSettings.mydashboard`? – Mihályi Zoltán Feb 25 '22 at 17:14
  • @MihályiZoltán, I have edited the question to include the `console.log` outputs. – jbreslow Feb 25 '22 at 17:20
  • 1
    `Object { test: "[\"authenticated\",\"administrator\"]" }` does not have a property called `content`. Therefore if you try to take the value for it, you'd get undefined. – VLAZ Feb 25 '22 at 17:26
  • 1
    It also looks like it is not an array, but an array serialized to JSON string – Mihályi Zoltán Feb 25 '22 at 17:28
  • @VLAZ, I have updated the code, tested, and updated the question with the results. Changing `test` to `content` didn't fix the issue. @MihályiZoltán Yes, the value coming back from Drupal is an array that has been serialized. – jbreslow Feb 25 '22 at 17:33

1 Answers1

1

Based on your data, your TypeScript definitions should look like this:

interface Settings {
    [index: string]: string;
}

And later parse the JSON:

const content: string[] = JSON.parse(drupalAndReactApp.content);
Mihályi Zoltán
  • 822
  • 6
  • 11
  • I am getting an error with this line, `const content: string[] = JSON.parse(drupalAndReactApp.content);` Error: `Argument of type 'string[]' is not assignable to parameter of type 'string'.` – jbreslow Feb 25 '22 at 17:45
  • 1
    Sorry, the value in Settings interface is string, not string[]. updated my answer – Mihályi Zoltán Feb 25 '22 at 17:50
  • I updated that line to this, `const content: string[] = drupalAndReactApp.content;` and it works! Edit: I tested it with your edit and that works as well. Thank you for the help. – jbreslow Feb 25 '22 at 17:50