jedireza/aqua

Best way to pass something from Config.js into the client ?

Closed this issue · 11 comments

whats the best practice ?

Good question. There really isn't a "best practice". What kinds configuration are you thinking (Ex: An S3 bucket name)? How often does it need to be updated (only once per app render)?

Its just a google clientid it would not change...

There's an app-state placeholder that can be used to send the redux store state to the client. Note: This is just a placeholder and isn't used for anything yet.

<script id="app-state"
dangerouslySetInnerHTML={{
__html: this.props.state
}}
/>

You could extend this idea to support a config prop and render a script tag with the id app-config:

<script id="app-config"
    dangerouslySetInnerHTML={{
        __html: this.props.config
    }}
/>

Then on the server, in your handler you'd do something like this:

const clientConfig = {
    s3BasePath: 'https://s3.amazonaws.com/mybucketname',
    googleClientId: 'some-client-id-thing'
};

// ...

request.app.config = 'window.appConfig = ' + JSON.stringify(clientConfig) + ';'

Then on the client you'd assume that window.appConfig was an object and access your info directly; window.appConfig.googleClientId.

hmm, had been trying something like this, but not working out so good:

class HomePage extends React.Component {
    render() {

        const neck = [
            <link key="layout" rel="stylesheet" href="/public/layouts/default.min.css" />,
            <link key="page" rel="stylesheet" href="/public/pages/home.min.css" />
        ];
        const feet = <script src="/public/pages/home.min.js"></script>;
        
        const googleClientId = Config.get('/google/clientId');
        const hostedDomain = Config.get('/google/hostedDomain');
        
        return (
            <Layout
                title="Home"
                neck={neck}
                feet={feet} activeTab="home" googleClientId={googleClientId} hostedDomain={hostedDomain}>
                <div id="app-mount"></div>
            </Layout>
        );
    }
}

class PlainLayout extends React.Component {
render() {

    return (
        <html>
            <head>
                <title>{this.props.title}</title>
                <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                <link rel="stylesheet" href="/public/core.min.css" />
                <link rel="shortcut icon" href="/public/media/favicon.ico" />
                <script type="text/javascript">
                    window.googleClientId='{this.props.googleClientId}'; 
                    window.hostedDomain='{this.props.hostedDomain}';
                </script>
                {this.props.neck}
            </head>
            <body>
                
                {this.props.children}
                <script src="/public/core.min.js"></script>
                {this.props.feet}
            </body>
        </html>
    );
}

}


in console I get unexpected token:
e="text/javascript">window.googleClientId=\&#x27;test\&#x27;; window.hostedDomain=\&#x27;test2\&#x27;;</script><script src="/public/pages/home.min.js"></script></

I don't think you can set the inside of a script tag this way without using dangerouslySetInnerHTML. You can see the in the output that some characters are escaped.

your solution worked nicely thanks 💯

I noticed you're using the older Layout component. Please note that last week I shipped a new universal front-end and no longer use that pattern.

whats the advantage of this new way and why called 'universal' ?

confused, app is still not isomorphic I thought ?

Universal and isomorphic are used interchangeably. The main front-end app is universal now. The admin and account areas are not.