DEV Community

MartinJ
MartinJ

Posted on • Edited on

2.3 A student's guide to Firebase V9 - A very gentle introduction to React.js

Last reviewed: March 2023

Introduction

This is a big moment!

If you're new to webapp development and have started at the beginning of this post series, you will have learned how easy it is to publish your ideas on the Internet using a combination of Javascript, Gooogle's Firebase and HTML.

Justifiably, you'll feel rather pleased with yourself. In principle, you could use these skills to build a webapp that would do literally anything you might imagine. Sadly, however, I now have to tell you that the techniques you've used so far won't get you very far if you're looking for employment as a software developer. Why? Because complex systems built this way take too long to code and are too difficult to maintain.

Here's the problem. Your HTML is good at defining a screen layout and your Javascript is good at assembling input to put into this. But the mechanism for linking the one to the other - telling the layout how it needs to change in order to reflect the new input is an idiosyncratic mess. This needs to change

So, welcome to the world of development "platforms" and "frameworks". Here you will find yourself using automation tools that allow you to create a "sketch" of your application and then leave some rather smart "transformations" to put this into practice automatically.

As a matter of fact, you've been using automation tools ever since you began to use VSCode to write your Javascript. Examples are VSCode's "intellisense" facilities that save you so much typing, and the built-in "syntax highlighting" and "syntax checking" tools that pick up your programming errors before they ever get near to triggering a browser error. However, none of this does anything to reduce the number of lines of code you have to write or to make your program more comprehensible.

In recent years, the software industry has been at a fast boil while some very clever people have worked on ways of tackling this problem. The results can now be seen in a dizzying assembly of competing products - React, Vue, Next.js, and Azure are just a few examples. This post is focused on React.js and does its level best to introduce you to some beautiful but rather complex ideas. It also provides some simple examples that you can easily use to try things out for yourself.

A word of caution though. This a looooong.... post and I suggest you take your time over it. The successive sections build logically to the point where you have actually deployed a React-based webapp onto the Internet, but it might be best to take a break between each section while you think over what you've just learned.

OK, I know you're going to ignore me, but don't blame me if you get a headache!.

What is React.js and how do I get started using it?

React.js was originally developed by Facebook in 2011. They used it to deliver their own web interface and React is now used by many other major players such as Netflix and Dropbox. What's more important to you is that it has now been around for a while and has acquired strong support in the software development industry. It's impossible to say what the future may hold but you can be assured that use of React.js will at least develop your Javascript skills. Whatever happens, these skills will stand you in good stead. The React.js framework also fits very comfortably with Firebase and the rest of the Google Cloud platform.

Please note that this post describes the current "functional component" style of React. Like the Javascript language itself, React has been the subject of much change since its inception. Be aware that web searches are likely to lead you to documentation that relates to the earlier "class components" version of React. These are likely to confuse you and are best avoided.

That all said, let's make a start

Assuming you're using VSCode, add a new project folder to your workspace, open a new terminal session on this, and enter the following command:

npx create-react-app .
Enter fullscreen mode Exit fullscreen mode

The . at the end of this command directs create-react-app to create and populate a React folder structure inside the current folder.

The dials on your electricity meter will now start to whir as npx downloads a vast number of library files. Try not to panic! After a minute or two you should receive a message telling you to type npm start.

Incidentally, just in case you feel you need to abort one of these terminal process, be aware that you can always do this by pressing the Ctrl and C keys simultaneously. Note also that, for Windows users at least, the enormous number of tiny library files downloaded by both React and Firebase into your project's node_modules folder can cause significant performance issues for subsequent deletion and copy actions. Version control systems like Dropbox and Onedrive may also struggle. It's probably a good idea to ration the number of new projects you create and also to consider whether you actually need an independent version control system for a VSCode project in the first place. If you check out VSCode's "timeline" feature you'll find that local version control is baked in here.

Anyway, onwards with npm start. What's all this about?

As you'll see later, while npx create-react-app has created a bunch of library functions for you to import into your code and deliver React magic, it has also installed a number of executables. The npm start script is one such. What this does is start up a server that grabs the code in your project, compiles it, and then launches the result in your web browser.

You haven't put any code into your project yet? Well, actually, you have because create-react-app has just put a demo there.

So, cross your fingers and, as instructed, type npm start into your terminal session.

Compiling your code is quite a heavyweight task so be prepared for another longish pause at this point. But eventually your browser will automatically spring into view displaying, initially, just a blank page succeeded shortly by the following image:

React logo

Hmm - very impressive, I'm sure. But what's the big deal here? Ah, note the suggestion that you might try to "Edit src/App.js and save to reload".

Locate the App.js file in your project folder and have a look at it. You'll find that it contains an App() function that returns something that looks almost, but not quite entirely unlike HTML (to quote Douglas Adams). Suppose you take a gamble with this and insert a bit of your own HTML. For example, you might try replacing the bit of App.js that currently says

        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
Enter fullscreen mode Exit fullscreen mode

with

        <p>
          Hello, Oh Brave New World.
        </p>
Enter fullscreen mode Exit fullscreen mode

Save App.js and look again at your browser page. Oh, my goodness! This now looks like:

React logo corrected

Take a moment to reflect on the significance of this. Previous posts in this series have described how you have to laboriously deploy your project to the Firebase host every time you want to test a change. Here you can test a change by simply saving the file!

What's happened here is that the npm start command has launched a server that is now "watching" your project. Any changes you might make here are immediately pushed through to the browser.

But this is just the start!

Building a webapp with React

Hang on to your hat now, because this is where your learning curve starts to steepen.

In the past I think it's reasonable to say that a webapp broke down into two distinctly separate components:

  • a block of HTML tags peppered with identifiers and
  • a block of Javascript that manipulated the program's data and then used those same identifiers to grab elements of the HTML and change their content.

In a React webapp the HTML block becomes something much more like a program in its own right. It acquires the ability to reference Javascript variables which it can then use to :

  • switch blocks of HTML on and off via conditional expressions.
  • launch Javascript map or forEach methods to output tabular data. React calls these structures Lists.
  • pass data to "pseudo tags" - blocks of HTML that have been allocated their own independent status because of their importance within the hierarchy of the program's output. React refers to these as Components

This HTML/Javascript hybrid was christened "Javascript XML" by React's developers - JSX for short

Why would you create this hybrid? Well, it paves the way for the real core of React's architecture which is how to deal with the grunt process of working out how to adjust the browser's display when the embedded Javascript variable references change. The "HTML program" also gives you a way of creating the promised "high-level sketch" of your architecture. OK, it's still a pretty crude way of delivering this, but it's way better than anything you've had before and will enable you to create some compact, comprehensible code. Looking around at the speed with which software-development technology is maturing I take this as a promising sign of good things still to come.

Anyway, let me give you an example. I think JSX's "conditional HTML" concept is the easiest to grasp, so I'll just use this for now. Let's say that you're aiming to deliver the following masterpiece - a webapp with a button that makes a paragraph appear and disappear.

Here's a JSX "skeleton" you might use for this (and please don't actually try this because it won't actually work as shown - I've got a bit more explaining to do yet):

<div style = {{textAlign: 'center'}} >
    <button onClick = {() => {{dogBarking = !dogBarking}}}>Toggle that Dog< /button> 
    {dogBarking ? 
    <p>Woof! Woof!</p> : 
    <span/>
    } 
</div>
Enter fullscreen mode Exit fullscreen mode

The important thing I'd like you to recognise in this "dog's breakfast" of pseudo-code is the idea that dogBarking (a Javascript variable that you've declared somewhere earlier in your code) is now somehow accessible to JSX and available to direct the generation of html.

The dogBarking variable is first referenced in the button tag's onClick function where its value is toggled when the event fires. It is then referenced again in the conditional statement expressed by {dogBarking ? to optionally select whether <p>Woof! Woof!</p> or an empty <span/> gets displayed.

Let's not get hooked up on the details of this for now, but at least note that variables seem to be indicated by the presence of curly braces and that conditional expressions are likewise surrounded by braces.

Also note that there's something funny about the styling of the div - JSX has replaced conventional CSS styling syntax with an object. What's happened here is that JSX has opened up a way to use variable references to replace CSS styles.

Anyway, this all said, the important question you need to be asking here is "if I toggle the button, how can that possibly change what is displayed on the screen?". Or, to use React's own way of expressing this - "what might prompt React to 're-render' the page?".Or even more technically, "what might prompt React to push appropriate updates to the browser's DOM (Domain Object Model)?".

Here then is the central concept underlying React - the idea of a "cycle" process that can be triggered to relaunch a JSX "HTML as program" and repaint the screen as directed by the latest values in the Javascript parameters that it references.

In React, these parameters are all expected to be stored as properties of an object that React refers to as the webapp's State. Let's say we've called this object screenState. In this case, the state object for the 'disappearing dog' webapp might look like

const screenState = {
    dogBarking: false,
}
Enter fullscreen mode Exit fullscreen mode

I think you're now ready for the "big reveal". In order to make it possible for you to dynamically refresh the screen when a State variable changes, the React library provides you with a function called useState(). Once seeded with a particular state variable, this allows you to register a mechanism that automatically re-renders the page when you change State's values.

I can't emphasise too much how valuable this is. For a complex screen hierarchy, working out the implications of parameter changes for the browser's DOM in an efficient manner can be a perfect nightmare. React relieves your program of all these concerns.

How, precisely, do you use "seed useState with a State variable" and what exactly is the "mechanism for changing State values"?

Take a deep breath now. This is achieved through one of the most bizarre pieces of Javascript syntax you've ever seen. It takes the following form:

const [myStateVariable, setMyStateVariable] = useState({
    property1: initial value,
    property2: initial value, 
    property3: initial value, .....
})
Enter fullscreen mode Exit fullscreen mode

Never mind for now how this works. For now, what matters most is what it does.

This statement is saying to useState "please let me use a new constant object called myStateVariable to define my webapp's output, let me initialise this with the following properties, and let me use a function I'm going to call setMyStateVariable if I ever want to change these".

This means that when you want to change a couple of properties in myStateVariable, say property1 and property3, you could do this with the following function call:

setMyStateVariable({
    ...myStateVariable, 
    property1:newProperty1Value,
    property3:newProperty3Value }
)
Enter fullscreen mode Exit fullscreen mode

If you've not encountered "..." notation before, this is an example "spread syntax" and it is used here to provide a quick way of telling useState to replace its current myStateVariable content with a new object containing "all the current properties of myStateVariable plus the following additions/amendments".

Anyway, the effect of this here is massive. When you use setMyStateVariable to updatemyStateVariable like this, because this is policed by useEffect, not only is myStateVariable updated with the new values of property1 and property3, but the webapp's display itself is also refreshed so that it reflects the new content of myStateVariable"

Wow! Let me say this again. When you change your program's state in a React webapp, your JSX automatically changes your webapp's output. Wow!

Here's a working version of 'disappearing dog'. You can try this out by simply pasting it over the current content of your App.js file :

import React, {useState} from 'react';

function App() {

    const [screenState, setScreenState] = useState({dogBarking: false})

    return ( 
        <div style = {{ textAlign: 'center'}}>
        <button onClick = { () => {
                setScreenState({dogBarking: !screenState.dogBarking})
            }
        }>Toggle that Dog</button>

        {screenState.dogBarking ? <p> Woof!Woof! </p> : <span />} 
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Save the file and you'll find (provided you've not closed down the terminal session on your project) that localhost:3000 now displays a page with a "Toggle that Dog" button. If you click this, the dog will "bark". Isn't technology wonderful?

Initialising State with data from an asynchronous source and then displaying the results in a React List

An information system will often need to begin by initialising its program state with data from an asynchronous source such as a Firestore collection. Typically you might be doing this in order to seed the option content for a select tag. But this creates problems because delays in the return of the data may leave users looking at a blank screen. When the data does eventually arrive, you then need to be able to detect this and refresh the screen appropriately. This can get quite messy!

React handles this problem by providing a function called useEffect() that allows you to register a packet of code as a function that runs when the webapp initialises and only then. If you arrange things so that this function updates state when it concludes, this will trigger a screen refresh and you can pick up where the initialisation left off.

The sample code shown below provides another version of App.js that might help you to get your head round this - it's intended to access an online Diary database and display Diary Entries for the current day.

The basic idea is that, on startup, the webapp should just display a title and some sort of "placeholder" while it waits for the asynchronous arrival of the diary entries. When these do eventually appear, the placeholder is removed and replaced with the asynchronous payload.

To keep things simple, I've written a little "promise" function to simulate the asynchronous bit - this is just to save you the trouble of configuring Firebase in your project. As things stand you can, as with my previous example, just paste the code below into App.js, save it and immediately observe the results on your browser's localhost page.

import {useState,useEffect} from 'react';

function App() {

    const todayDate = new Date().toISOString().slice(0, 10) // produces yyyy-mm-dd

    const [screenState, setScreenState] = useState({
        entriesLoading: true
    })

    useEffect(() => {
        async function getDiaryEntries() {
            const diaryEntries = await simulatedFirestoreAccess();
            setScreenState({
                 ...screenState,
                entriesLoading: false,
                diaryEntries: diaryEntries
            })
        }
        getDiaryEntries()
    }, []);

    async function simulatedFirestoreAccess() {
        // simulated asynchronous Firestore Collection reference returning two diaryEntry records
        // after a delay of 1 second

        const myPromise = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve([{
                    entryTime: "9.00",
                    entryDetail: "Have breakfast"
                }, {
                    entryTime: "12.30",
                    entryDetail: "Have lunch"
                }]);
            }, 1000);
        });
        return myPromise
    }

    return ( 
        <div style = {{textAlign: 'center'}} >
        <p> Diary entries for { todayDate} </p>

        {
            screenState.entriesLoading ? <p> ...loading diary entries...! </p> :
            screenState.diaryEntries.map((diaryEntry) => {
                return <p> <span> {diaryEntry.entryTime} </span> - <span>{diaryEntry.entryDetail}</span> </p>
            })
        } </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

When you've saved your updated App.js you should see that your local host browser page is displaying a title followed by a line that initially says simply ".. loading diary entries ...!". After a second or so, however, this should be replaced by the simulated diary entries. Try refreshing the page to make sure you get the full effect.

Let me walk through the code to clarify what is happening here.

  1. The webapp starts, initialises its todayDate and screenState constants and then hits the useEffect reference. This causes it to run the getDiaryEntries function which in turn triggers the asynchronous simulatedFirestoreAccess function.

  2. The webapp has now split into two parallel "threads" of activity - one is going to charge straight ahead and perform App.js's return() statement, and the other is going to idle for a second or so while it performs its asynchronous activity.

  3. Sticking with the first thread, this will, first of all, render the title with its todayDate reference (note that this show that it's not necessary for all local data used by JSX to be in State - you just need to be aware that values here will be re-initialised every time the webapp runs a render cycle).

  4. This first thread now hits the {screenState.entriesLoading ? condition. Because screenState.entriesLoading is still set to its initial setting of true at this point, the webapp will hit the "ternary"'s first option (see below for a note on ternary syntax) and display ".. loading diary entries ...!". The cycle is now concluded and this thread halts.

  5. A second or so later, however, the second thread comes back to life. The const diaryEntries = await simulatedFirestoreAccess(); statement in simulatedFirestoreAccess() resolves and control moves on to the setScreenState({ entriesLoading: false, diaryEntries: diaryEntries }) statement. Because this changes screenState, React now re-renders the display using the new state properties.

  6. Although this second cycle starts from scratch in App.js, the useEffect is not launched this time and so control moves straight on to render the component's return() statement. The title and date are unchanged so JSX won't touch these. But when control hits the {screenState.entriesLoading ? condition, the new entriesLoading setting will now instruct it to use the .map instruction to render the simulated diary entries. The magic in React's rendering logic will then automatically replace the "placeholder" message with the webapp's long-awaited data.

If you're still getting your Javascript up to speed, you might find the .map instruction a bit alarming. Let me break it down for you.

First of all .map is just a "method" possessed by all arrays. It takes, as an argument, a function that will be executed for every element in the array that it's called on. In this case, my array is full of simulated diary entries so, each time this function runs, it does so on a different diary entry. The (diaryEntry) => {}bit of the code is me setting up this function and allocating a name that I can use in its code to reference the diaryEntry presented to the function for each iteration.

Incidentally, there are quite a few ways in which I might have coded the definition of this .map method's function. The => (arrow notation) form is a sort of shorthand really. Think of it as saying "here's a function with these arguments that does this". It may look a bit strange at first but I recommend you try to get used to it because this is something that you'll use frequently in modern Javascript and which will save you a lot of typing.

Returning to my explanation of the payload of a .map function. In this particular case, the action of the function is specified as return (<p key={diaryEntry.entryTime}><span>{diaryEntry.entryTime}</span> : <span>{diaryEntry.entryDetail}</span></p>).

Now, what on earth is all that about?

Firstly, you might recognise the return() bit as another instance of the return() that you've already seen in the main body of App.js itself. I've not commented on the strange structure of the App() function so far but I'll pick it up in the next section where I talk about Components - for now, just let's say that this bit of code is operating as a sort of mini App.js. Potentially it might have a render cycle all of its own!

Within the body of the map's return(), I think that things get a bit clearer. Basically, this is just rendering the contents of the two properties of each diaryEntry - diaryEntry.entryTime and diaryEntry.entryDetail into a pair of <span> tags. The only unusual feature is the strange key property attached to the parent <p> tag. As stated earlier, the output of a map is handled by React as a List. Lists are a common structure in webapps and may become very large. React needs to ensure that it can render and re-render them efficiently - but it needs your help here. You do this by giving each entry in a List a unique identifier.

Note on Ternary syntax. A ternary in Javascript is a shorthand "if/else" structure used to simultaneously declare a new variable and set its content. It takes the form:

const myNewVariable = (conditional expression) ? valueA : valueB 
Enter fullscreen mode Exit fullscreen mode

The result of this will be a new constant called myNewVariable whose value will be valueA if if true and valueB otherwise. JSX uses the same ? and : syntax to switch the generation of html blocks.

This may look strange to you at first, but once you get used to it you won't be able to imagine life without it!

Styling in JSX

As demonstrated briefly above, the style value of a conventional HTML tag's <tag style = 'property1:value1; property2:value2 ....'/> is replaced in JSX by a Javascript object. The structure of a style object in JSX might look like this:

const myStyleObject = {
  property1: value1,
  property2: value2,
  // more properties and values
}
Enter fullscreen mode Exit fullscreen mode

Here, each property is a CSS characteristic that you want to style, such as "font-size", "color", "background-color", etc. But the difference is that the property names are now referenced in camelCase, not separated by hyphens as in CSS. So CSS's font-size becomes fontSize in JSX

Property values can be numbers, strings, or any other valid Javascript data type.

Here's a JSX example that styles a tag with a red background and white text:

<tag style={{backgroundColor: "red", color: "white",}}/>
Enter fullscreen mode Exit fullscreen mode

It may sometimes be more convenient in a React webapp to declare your style object with a const myStyleConstant = { ... } in your component and reference it as

<tag style={myStyleConstant}/>
Enter fullscreen mode Exit fullscreen mode

This arrangement makes it very easy to manipulate tag styling by modifying the style constant's properties.

If you prefer, you can still import a conventional css stylesheet into a webapp. Classes are applied to a tag in JSX by declaring a className qualifier, as in the following example:

import '../styles/globalstyles.css';

function myComponent() {
    return{
        <div className="myCssClass1 myCssClass2 ....etc" />
    }
}
Enter fullscreen mode Exit fullscreen mode

The style content of a stylesheet like this is constructed in the conventional way (ie with hyphenated names etc).

The "Component" approach to webapp design

I'm sure you'll appreciate that the simple React webapp examples described by this post are a million miles away from the reality of complex applications like the Facebook or Amazon sites. You're not going to squeeze Facebook into a single App.js file!

In practice, React needs to enable you to build your webapps as a hierarchy of design elements - Components is the word that they actually use. You've already seen an example of a Component in the shape of the App() function. A component is just a function with a return() full of JSX. What you've not seen is how, through the wizardry of the React compiler, such a function can then be referenced in JSX as if it were a new HTML tag.

Have a look at the src/index.js file that launches src/App.js. Inside there, the examples you've been running are the result of React rendering the following code in src/index.js

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

React seems to have invented a new html <App> tag!

As an example of how you might use this yourself, consider the sample React List you met earlier:

screenState.diaryEntries.map((diaryEntry) => {
            return ( 
                <p key = {diaryEntry.entryTime}> 
                    <span>{diaryEntry.entryTime}</span> - <span>{diaryEntry.entryDetail}</span > 
                </p>)
Enter fullscreen mode Exit fullscreen mode

In other circumstances this might have been written as

screenState.diaryEntries.map((diaryEntry) => {
            return ( <DiaryEntry key = {diaryEntry.entryTime} diaryEntry = {diaryEntry}/>)})
            )
Enter fullscreen mode Exit fullscreen mode

where App.js subsequently declared as a DiaryEntry() function as follows:

function DiaryEntry(props) {
  return ( 
    <p> 
        <span>{props.diaryEntry.entryTime}</span> - 
        <span>{props.diaryEntry.entryDetail}</span > 
    </p>
  )
}

export default App;
Enter fullscreen mode Exit fullscreen mode

The advantages of doing this might not be immediately obvious but, suppose that the output rendered by DiaryEntry had been something really complicated with sub-lists of its own. In such a case I think you can easily imagine how the insertion of a complex stack of code into the heart of App.js would impair its clarity.

Component design allows you to "structure" JSX in the same way as might use functions to structure your Javascript. Similarly, because components can be allocated their own files and passed around via export and import statements, they also allow you to share code within and between webapps.

An issue that has to be faced when using Components, however, is that you will generally need to provide a mechanism for passing data to them. In the example above, the DiaryEntry component (the capitalisation of the first letter is a widely-accepted convention to alert you to the special status of a component function) needs to be supplied with a diaryEntry object. This is done in this case by supplying additional properties to the <DiaryEntry> reference. These take the form of a property name ( diaryEntry in this case) followed by a reference to the data item you want to attach to it. Inside the component function meanwhile, this data can be retrieved as props.propertyName (eg props.diaryEntry.entryTime ), where props is declared as an argument to the function. The word props here is to be read as shorthand for "properties".

Webapp "Routes"

While the "component" technique described in the previous section provides a basic tool for structuring your application you'll find that, in practice, you need more than this. Users have always enjoyed the ability to use a browser's "page history" facility" to unwind their track through a system. Despite the fact that what we're developing here is a "single-page" webapp, React needs to ensure that users still have access to "page history" for the various elements of the webapp's structure.

Webapps deal with this problem by means of arrangements that define "logical" pages to overlay the physical single-page design. One popular way of doing this is through an extension called React-router.

Confused? I'd be surprised if you weren't, but this is too complex an issue to describe here. When you have a bit more time, you might find it useful to look at What's a 'Single-Page' App? Learn about React-Router (and Vite). in this series.

Coding Input fields in a React webapp

You're going to want to be able to read data into your webapp. React handles this by attaching onChange functions to input fields and using these to update State. This way State continues to provide a complete representation of the screen display.

Because this post is already way too long I'm just going to show you how you might handle simple input types such as text and date. The following template included in your JSX would maintain a property called myInput in State

<label>My Input Field: </label> 
<input type='text' // substitute 'text', 'date' etc, as appropriate for 'input type'
    name='myInput' // substitute a unique State property name for 'myInput'
    value={screenState.myInput} // substitute the name of your component's State
    title='Enter the value for this entry' //substitute appropriate advice
    onChange={handleInputChange}/>
Enter fullscreen mode Exit fullscreen mode

Additional properties such as maxLength, size, style, placeholder and autoComplete properties might also appear here.

Here's the accompanying handleInputChange function. This needs to be placed somewhere inside the body of the component function.

    function handleInputChange({target}) {
        // For input "name", set State's target.name property to target.value 
        setScreenState({ //substitute the name of your State update function
            ...screenState,  //substitute the name of your State constant
            [target.name]: target.value 
        })
    }
Enter fullscreen mode Exit fullscreen mode

Your heart may sink once again at the sight of yet more exotic javascript syntax. But cheer up - as with the State declaration statement, what really matters here is what the code does rather than how it does it (it's actually using "destructuring" syntax to unpack the event object returned by onClick). What this code says is "when this function is launched by the onClick on an input field that I've called myInput, please put the value of this field into a State property called myInput".

Note that while React is happy to create new State properties for input items through the handleInputChange() function, it will be even happier if you explicitly initialise them first in State. I think this is actually a good practice anyway because it clarifies your code.

To give your confidence a boost I suggest you try adding the sample code above code to App.js.

If you do this, I suggest that you place an alert(JSON.stringify(screenState)) instruction immediately before App.js's return statement. This way you'll be able to see more clearly see what is happening. The statement displays an alert box containing a JSON representation of screenState and you will be able to see how your State changes every time you press a key in the input field.

More complex input cases such as select and checkbox and file follow this general theme but introduce subtle variations. It would be a distraction to describe these here, so please refer to 10.2 Reference - React JSX Templates for further details.

In passing, you may have spotted the total omission of references to the HTML form tag in any of the above. I think it's safe to say that HTML's traditional form concept is more or less redundant in a React webapp. The use of a <form> as a way of "submitting" a "parcel" of data from a client screen to a host process via a <form>'s submit button is now replaced by the use of buttons that you define yourself.

Debugging in React

Your first experience of coding in React is likely to be somewhat alarming - I don't believe I've ever seen so many error messages as when I wrote my first React webapp. If you leave out just one of those fiddly JSX brackets or chevrons, VSCode will turn your entire screen red!

Once you get your eye in, however, things will become easier. The trick is to hover over the first occurrence of an error indication (a red underscore) to display a tooltip that will provide a clue to the possible cause. A very common source of error is JSX's requirement that "JSX expressions must have one parent element." - this commonly means that you need to put a <div></div> pair around a bunch of tags. Forgetting to close a tag is another common source of meltdown. The problem will usually be located immediately before the first error indication.

Just take a deep breath, check systematically, and refer back to the templates mentioned above. It also sometimes helps to temporarily remove problematic sections and debug them independently. Map statements are the most frequent source of problems. Here, while there are many ways in which you can define functions in Javascript, you'll find it's generally best to stick to the one supplied in the "Diary Entry" example above.

The above advice should help you to get your React webapp through VSCode. Unfortunately, problems will continue to be reported when you run npm start.

Initially, you'll find that the React compiler does a great job at picking up undefined variables, etc, and will display error details in your localhost browser tab. Just keep fixing files and re-saving.

But then, even after you've got your webapp to compile, you may still find that you're looking at a blank localhost screen. This is because the webapp execution has errored and you now need to use the browser's inspect tool to find out what's going on.

Errors reported by the inspector tend to be of a technical nature and the accompanying messages are correspondingly expressed using highly technical language

You need to take a firm grip on yourself here. With experience, you'll find you take all this in your stride, but at first, it's quite unsettling. Many of those red messages will just be "warnings" rather than "errors", but the ones labeled as errors need to be fixed before your webapp will run.

Once you've overcome your panic and read the error detail carefully, I guarantee that you'll eventually work out what is going wrong. Take your time here. Because you feel you're so close to getting your webapp working, the natural instinct is to rush at the code and make changes wildly. This probably won't help much! It's often better to take a break and give yourself time to think through the problem. Remember that you can always try pasting an error message into stackoverflow and searching here for assistance. Stackoverflow has got me out of a hole on many occasions.

Stick with it. With persistence you will get that webapp working.

Deploying a React webapp to the Web

So far, this post has only talked about running a webapp locally through the React server. How do you make your webapp available to the general public on the web?

At first sight, this looks as if it may be quite a problem, but in actual practice, it turns out to be very simple. The first step is to use another React script to create a "build" directory to store the structured information generated by the React compiler.

You do this by simply typing the following into a terminal session on your project*

npm run build
Enter fullscreen mode Exit fullscreen mode

When this is finished, the next step is to use the Firebase deployent tool to upload the contents of your "build" directory" to the web.

Here, you're obviously going to need a Firebase project. If you've not been here before, you might find it worthwhile studying [2.1 A student's guide to Firebase V9 - Project configuration](https://dev.to/mjoycemilburn/a-beginners-guide-to-Javascript-development-using-firebase-v9-part-1-project-configuration-5bo3 in this series.

If you're an old hand at working with Firebase you've probably already got a test project somewhere that you can reuse here. In this case, if you just want to try deploying the demo code you've been working on in src/App.js above, the procedure would be as follows:

  1. Type firebase init hosting into your Vscode terminal session to link your VSCode project (ie the one containing your App.js) to the Firebase project you want to use to host it. The hosting script will ask you a few questions. Respond to these as follows:

    ? What do you want to use as your public directory? build
    ? Configure as a single-page app (rewrite all urls to /index.HTML)? Yes
    ? File build/index.HTML already exists. Overwrite? No

    These responses will ensure that deployment will use the results of your npm run build and prevent Firebase from overwriting create-react-app's demo index.HTML file with its own demo index.HTML.

  2. Now type firebase deploy

The result of all this will be a url for you to paste into your browser's url field. Behold, your React webapp is now running on the Internet. Hurrah!

Congratulations for making it to the end of this mega-post - I hope that you have found it useful.

For a full list of the posts in the series, please check out the site index at ngatesystems.com.

Top comments (0)