4

I recently got started with web development. And I am stuck with sth that's probably a trivial problem. I am trying to figure out how I can pass data from my dynamically created index.html to my (typescript) react frontend (created via create-react-app).

Suppose we have a flask web server that, when the '/' resource is requested, gathers some initial user data, instantiates a page template with it and returns that page:

# flask webserver
from flask import Flask
from flask import render_template
app = Flask(__name__)

@app.route('/')
def index():
   initial_user_data = {"foo":"bar",
                        "baz":"biz"}
   return render_template('index.html', initial_data=initial_user_data)

if __name__ == '__main__':
   app.run(debug=True)

For the sake of simplicity initial_user_data stores hard-coded data here. In my actual use case the dictionary gets populated with various user-specific data items that are read from files etc.

Next, let's assume index.html uses the initial_data.

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <title>React App</title>
  </head>
  <body>
    <script>
      initial_data = {{initial_data | tojson}}
      console.log(initial_data)
    </script>
    <div id="root"></div>
    ...
  </body>
</html>

When we now start the webserver and open a browser to navigate to the page when can see the initial_data being logged to the browser's console output. So far, so good.

Now my problem: how can I pass initial_data to my (typescript) react components? Conceptually I want to do sth like this:

// App.tsx
import React from 'react';

const App: React.FC = () => {
  // make use of 'initial_data'
  const init_data = initial_data;
  return (
    <div ...
    </div>
  );
}

But yarn build will give me

Cannot find name 'initial_data'.  TS2304

    4 | 
    5 | const App: React.FC = () => {
  > 6 |   const init_data = initial_data;
      |                     ^
    7 |   return (
    8 |     <div className="App">
    9 |       <header className="App-header">

How can I make initial_data accessible to my react components?

Edit: If this pattern of passing something from the index.html (that gets created on the backend when a clients connects) to my typescript react components is flawed then I'd also accept an answer that points me to the correct pattern in this case.

Something along the lines of (obviously just making sth up, just trying to illustrate what I mean)

  1. Define a typescript data type that stores the user data that can be accessed from all your components
  2. in your main react component use a life-cycle method like 'componendDidMount' to send a request to the backend to fetch the initial_data
  3. When the response comes back store it in 1)

I'd accept an answer that adds shows some sample code for 1) 2) 3)

Many thanks for your help!

Matt
  • 355
  • 3
  • 12

1 Answers1

5

When you pass global variables inside a react component, it's always a better way to pass it using the window object. In this case, you need to pass it as window.initial_data. This informs the linter and react that it's a global variable. As it is not defined inside the file.

reflexgravity
  • 910
  • 10
  • 17
  • Upvoted your answer! Thanks. This works with plain javascript, but fails with typescript (which is my use case). If I understood your suggestion correctly you suggest to store `initial_data` in `window` in `index.html` and then read it in my react code, correct? That gives me `Property 'initial_data' does not exist on type 'Window'` Happy to accept your answer once we get it working with typescript. – Matt Aug 10 '19 at 21:43
  • 2
    Do you think this would solve your problem? I'm not a master in TypeScript. So can't help here. https://stackoverflow.com/questions/38906359/create-a-global-variable-in-typescript – reflexgravity Aug 10 '19 at 21:47
  • Thanks. I read through the answers. From what I can see those solutions are for making global variables available .tsx files. My (apparently weird) use case is to write the variable in a ` – Matt Aug 10 '19 at 22:00
  • @Matt: variables declared in script tags are global variables. They will be available to other scripts or in the console. Try `console.log(window.initial_data)`. Did you try to use any of the answers in the linked question? – Håken Lid Aug 12 '19 at 21:08