user988544
user988544

Reputation: 576

ReactJS access variable out of scope in render function

I have a config file that I would like to import and render/loop through in one of my components. The config file:

data.config.js

export const data = {

  clientData: {
    name:'Lynda', 
    age:'53', 
    userid:7896
  },
  otherData: [
    {
      option1: 'good;', 
      option2: {type: 'confirmed'}, 
      option3: ['u','g','l','y']
    },
    {
      option1: 'awesome;', 
      option2: {type: 'temporary'}, 
      option3: ['u','g']
    },
  ],
};

component.js file

import { data } from '../config/client/data.config.js';
..

var clientData = data.clientData; // console o/p returns object key and values
var otherData = data.otherData; // console o/p returns object key and values

.. 

render() {
  const {
      title,
      favicon,
      socialMediaDesc,
      socialMediaImg,
      ...
    } = this.props;

...
  return(
    <html className="no-js" lang="en">
      <title>{title}</title> // works as expectec 
      ...

      <script dangerouslySetInnerHTML={{ // eslint-disable-line react/no-danger
        __html: `

        for (var client in ${clientData}) {
          if (${clientData}.hasOwnProperty(client)) {
            (function(key, value) {
              console.log(key, " : ", value);
            })(client, ${clientData}[client]);
          }
        };
      `,
      }}
    </html>
  )

}

Expected console o/p:

name  :  Lynda
age  :  53
userid  :  7896

Result that I am getting: Uncaught SyntaxError: Unexpected identifier as value of ${clientData} is [object Object]

How can I access clientData and otherData key and values inside the render function?

Upvotes: 0

Views: 1529

Answers (1)

Mike Cluck
Mike Cluck

Reputation: 32511

You seem to be misunderstanding how template strings work. They immediately create a string where each ${thing} is replaced by the string value of that thing.

Check out what happens when I do something similar and just print the string.

const clientData = {
  name: 'Lynda',
  age: '53',
  userid: 7896
};

const html = `
for (var client in ${clientData}) {
  if (${clientData}.hasOwnProperty(client)) {
    (function(key, value) {
      console.log(key, " : ", value);
    })(client, ${clientData}[client]);
  }
}`;

console.log(html);

You see how that works? Since clientData is an object, it's generating [object Object] as part of the string.

If you really want to dangerously generate some JS (which I would thoroughly advise against), then consider generating the code before then inject it as HTML.

const clientData = {
  name: 'Lynda',
  age: '53',
  userid: 7896
};

let html = '';
for (var client in clientData) {
  if (clientData.hasOwnProperty(client)) {
    html += `
(function(key, value) {
  console.log(key, " : ", value);
})(${client}, "${clientData[client]}");`;
  }
}

console.log(html);

I'd like to point out that unless you're doing something really tricky then there's no reason to wrap that code in a <script> tag. Just run it as is. After all, you're already in the middle of running some JS. May as well run the rest right away.

const clientData = {
  name: 'Lynda',
  age: '53',
  userid: 7896
};

for (var client in clientData) {
  if (clientData.hasOwnProperty(client)) {
    (function(key, value) {
      console.log(key, " : ", value);
    })(client, clientData[client]);
  }
}

Upvotes: 1

Related Questions