Category Archives: ReactJs

Debugging an Asp.Net Core React Application in Azure

I’ve recently been working with an Asp.Net Core ReactJS application. When trying to debug this remotely, I switched on Development mode in order to get a stack trace when it crashed:

Instead of the stack trace, I got this:

An unhandled exception occurred while processing the request. AggregateException: One or more errors occurred. (One or more errors occurred. (The NPM script ‘start’ exited without indicating that the create-react-app server was listening for requests. The error output was: )) System.Threading.Tasks.Task.ThrowIfExceptional(bool includeTaskCanceledExceptions)
InvalidOperationException: The NPM script ‘start’ exited without indicating that the create-react-app server was listening for requests. The error output was:

This is, in fact, caused by the following code:

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (_env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });

This uses the setting “Development” to determine whether to start a local React server; which will fail on a remote server. However, I want to see a stack trace, which is here:

            if (_env.IsDevelopment())            
            {
                app.UseDeveloperExceptionPage();
            }

The problem here is that “Development” has two functions – it displays a stack trace, and it manages all these variables that should only run on your machine. What we need are two settings that both mean “Development”; one that means that we’re running locally, and one that we’re trying to debug. Start with an environment variable:

You can set this to anything you choose… But I’ve gone with “LocalDevelopment”.

The next step is to find all the places that check IsDevelopment, and replace them. What we essentially want is this:

                //if (_env.IsDevelopment())
                if (_env.IsEnvironment("LocalDevelopment"))
                {

However, we can create our own extension method, so that the code looks a lot neater:

        public static bool IsLocalDevelopment(this IWebHostEnvironment env)
        {
            return (env.IsEnvironment("LocalDevelopment"));
        }

Remember that IsEnvironment() is actually an extension method itself, so you would need to include:

using Microsoft.Extensions.Hosting;

In your extension class.

What to change

The following places will, at a minimum, need replacing for a standard web app. The stack trace should be displayed in either situation:

        public void Configure(IApplicationBuilder app)
        {
            if (_env.IsDevelopment() || _env.IsLocalDevelopment())                  
            {
                app.UseDeveloperExceptionPage();
            }

The React check that started all this:

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (_env.IsLocalDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });

Also, if you’re using local secrets, you’ll need this in Program.cs:

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder
                        .ConfigureAppConfiguration((hostingContext, config) =>
                        {
                            if (hostingContext.HostingEnvironment.IsEnvironment("LocalDevelopment"))
                            {
                                config.AddUserSecrets<Program>();
                            }

Because, by default, local secrets are only added for Development only.

Summary

That’s it, you can now set the ASPNETCORE_ENVIRONMENT to Development on a remote server, and you should get a stack trace.

React, Redux, and Typescript – Why, What and How

This article covers adding Redux to an existing React application.

Redux is one of those technologies where you get introduced to it, and you think: this seems overly complex to solve such a simple problem. Quite often, this is, in fact, the case. I once read a post (which I cannot find) by Dan Abramov where he said a similar thing himself. Redux is a state manager, and if you’re using it for React, React does have facilities to manage its own state, so you may not need Redux.

In fact, from what I’ve seen, I’d say you’re better leaving it until you know you need Redux.

Why

So, how will you know when you need Redux?

Well, you’ll know because you’ll raise some state, and suddenly realise that you’ve raised it into a component that has no business managing that state. My specific example was trying to manage user permissions.

Imagine the following menu structure:

Layout.tsx
	NavMenu.tsx
		NavItem (React-Strap)
		LoginMenu.tsx (accesses the DB to get user info)

I needed to store a user permission, and conditionally display a menu option (NavItem); these are held in a LoginMenu component. This meant that my state would need to be in NavMenu.tsx – but that’s a strange place for the state regarding a user to live. Additionally, other parts of the application would need access to this, and so it’s time for a state manager.

What

Okay, we’ve talked about why you might want to add Redux. Let’s see, exactly what Redux is. Essentially, there are three concepts to Redux. Before I continue with my second rate explanation, I would strongly suggest you jump over to Dave Ceddia’s blog. If you’re trying to do this in Typescript, then come back afterwards – otherwise, stay there, there’s nothing I can tell you that he doesn’t cover in this article.

Actions

An action is simply an object that contains a property called type. It can contain other objects, too, and is used to send information from your application into the Redux Store.

Reducers

Reducers are the engine of Redux. They accept an action, and the existing state of the application, and they return a new state.

Store

The store holds the current application state. You cannot change this directly, but through an action.

How

(In this section, I’ll include some imports and file names – I’ll talk about project structure towards the end, and the imports and filenames will make sense then)

Let’s imagine that your application is a game, where you can move a character left and right; your application state might look like this:

export interface IStore = {
    position: 0
}

We’ll also need to create the store, which we can do in the same code file:

Store.tsx

import { reducer } from '../State/Reducer';
import { createStore } from 'redux';

export interface IStore {
    position: number;
}

const store = createStore(reducer);
export default store;

Okay, so we have a state: we said that actions are the only things that can affect state (in fact we said through an action): let’s see what an action might look like:

export const MOVE = 'MOVE'

interface MoveAction {
    type: typeof MOVE
}

This would be sufficient, at least, this is all Redux needs; however, we need to know which way to move, etc. Convention seems to be to add a payload property; let’s see what that might look like:

Actions.tsx

export const MOVE = 'MOVE'
export interface Message {
    user: string
    message: string
    timestamp: number
  }
  
interface MoveAction {
    type: typeof MOVE
    payload: Message
}
    
export type ActionTypes = MoveAction;

I’ve used a generic Message – you could make this specific to your action, but this sort of approach means that your messages are consistent across actions.

So, now we have a store (somewhere to keep the state), and an action something to indicate that we wish to update the state. However, looking at the action, it doesn’t seem to do too much updating… In fact, it’s just a message – it could even be just a string. We now need the final piece of the jig-saw: the reducer takes the action and updates the state; let’s see what that might look like:

Reducer.tsx

import { InitialState } from './Store';
import { ActionTypes, MOVE } from './Actions';

export function reducer(state = InitialState, action: ActionTypes) {  
    console.log (action);
    switch (action.type) {
      case MOVE:
        return {
            ...state,
            position: state.position + parseInt(action.payload.message)
        }
        
      default:
        return state;
  
    }
    
}

There’s quite a lot here: (we’ll come back to InitialState shortly). Let’s go through a piece at a time.

The first thing we’re doing is checking the type parameter:

    switch (action.type) {
      case MOVE:

In a real world situation, there would be many options: you’re unlikely to have a single action, so the switch statement is necessary.

Remember earlier, we defined the action as MOVE:

export const MOVE = 'MOVE'

Which enables us to check for MOVE, rather than the magic string “MOVE”.

Inside the MOVE block, we’re accessing the payload:

      case MOVE:
        return {
            ...state,
            position: state.position + parseInt(action.payload.message)
        }

The reducer must be a pure function: that is, it accepts and returns data, but it does not change anything; as a result, we’re returning a new version of the state that was passed in. We’re setting the new state to have a position which is based on the current position, but we’re not changing the state.

This code will crash if the message is set to “qwerty” (so if you’re doing this sort of thing yourself, you should do it better than I have!)

Finally, the default: block simply returns the same state that it was given; i.e. the state remains unchanged.

Initial State and Project Structure

I said we’d come back to initial state. In the reducer, we have the following:

export function reducer(state = InitialState, action: ActionTypes) {  

We have to define a starting state for the store; and you can do that like this:

Store.tsx

export const InitialState: IStore = {
    position: 0
}

Before we move onto the application changes, let’s quickly talk about where this all goes. The frustrating answer is, it’s up to you; however, I found a structure like this quite useful, as it keeps all the Redux plumbing in a single place:

Plugging this into your app

So far, we’ve created a lot of code, but it’s been completely separate from your React application. Plugging it in is actually quite trivial. Let’s start with Index.tsx; you’ll need to import your reducer:

import { reducer } from './State/Reducer';

In the render function, you’ll then need to add the store into the DOM:

ReactDOM.render(
  <Provider store={store}>
    <BrowserRouter basename={baseUrl}>
      <App />
    </BrowserRouter>
  </Provider>,
  rootElement);

We can then access the store inside any component by simply referencing the Store.tsx:

import store from '../../State/Store';
import { MOVE } from '../../State/Actions';

And then calling the dispatch function:

            store.dispatch({
                type: MOVE,
                payload: {
                    user: user.name,
                    message: "1",
                    timestamp: new Date().getTime()
                }
            });

We can also get the state by using this:

store.getState();

Connecting the State

This works okay, but there is an easier way; you can use the Redux Connect function. Essentially, instead of exporting the React class, you instead export a wrapper for it. Before that, though, you need to work out what you’re trying to map. You’ll need to split your props into three groups:

1. Props from the store that you want in your component
2. Props that you want to be passed into your component
3. Props from the store that are actually functions; that is, dispatch functions

You would then rewrite your component like this:

import { connect } from 'react-redux';
interface StoreProps {
   position: number;
}
interface OwnProps {
   ...
}
interface DispatchProps {
   ...
}

type Props = OwnProps & StoreProps & DispatchProps;
interface IState {
   ...
}
class GameComponent extends Component<Props, IState> {
   ...

Notice that you’re no longer exporting the GameComponent class. Instead, you add the following:

function mapStateToProps(state: IStore) {
  return {
    position: state.position
  };
}
export default connect(mapStateToProps)(GameComponent);

This allows you to expose only the properties relevant to the component, but not the properties that you take from the Redux store.

References

https://blog.logrocket.com/why-use-redux-reasons-with-clear-examples-d21bffd5835/

https://daveceddia.com/redux-tutorial/

https://daveceddia.com/access-redux-store-outside-react/

https://redux.js.org/recipes/usage-with-typescript

Capturing Url Parameters in ReactJS using Typescript

This sounds like it’s a very easy thing to do. There are a lot of resources out there on the web, however, I certainly did not find it straight-forward.

My use case here was very simple: the site had failed to do something, I had the reason, and I just wanted to display that to the user (maybe at some stage I’ll move the response into the body, but I thought this would be an easy option for now.

How

The first step is to bring RouteComponentProps into your React file:

import { RouteComponentProps } from 'react-router';

Your component should have a class signature similar to this:

export class AddSiteFailure extends Component<IProps, IState> {

If you’re interested in some common Typescript syntax differences for React, I recently posted on this very subject.

In the above class definition, we’re accepting IProps and IState. IProps needs to be amended slightly:

interface IProps extends RouteComponentProps<IMatchParams> {    
}

interface IState {
}

So, we’re inheriting from the RouteComponentProps that we imported earlier, and we’re telling it that the structure of the parameters will be defined in an interface called IMatchParams. We’ll need to define that:

interface IMatchParams {
    reason: string
}

Okay, so far, we have a standard props structure, but we’re now inheriting from this new RouteComponentProps, and we’re telling it that the URL parameters will be defined in the interface IMatchParams. So, why does IMatchParams have a string property called “reason”?

The answer to that lies in your App.js / App.tsx. This is the file that manages the routing of your app. In the Render method, your file should have an entry similar to this:

<Route path='/addSiteFailure' component={AddSiteFailure} />

So, you need to tell it that you’ll be accepting a parameter, and you need to give that parameter a name; for example:

<Route path='/addSiteFailure/:reason' component={AddSiteFailure} />

Now, when you navigate to the page, the additional Url parameter will be internally referred to as “reason”, which is how it maps to IMatchParams.reason.

Force React Components to sit Side-by-Side

For anyone that knows me, they’ll know that UI and UX is not exactly my strong suit. If I had my way, we’d all just use console applications like this:

>placeorder /productcode coffee /quantity 1

Unfortunately, the trend seems to have gone a different way, and now we have CSS. CSS is a brilliant idea; however, you need to be able to visualise what you want your stuff to look like first.

Anyway, onto this post. If you know anything about CSS or Bootstrap, then you’ve probably already read everything that could interest you about this post!

In my latest project, I have a search box, and I wanted to line up the controls on the screen like this:

Search         [Search Text]        [Search Button]

I’m using React, so the original code looked like this (more or less):

<label>Search</label>
<input type='text'/>
<SimpleButton buttonAction={props.searchAction} buttonLabel="Search" />            

And it rendered like this:

Search         [Search Text]        
[Search Button]

My first gambit was to define a CSS style (so I can now put “Front End Developer” on my CV):

.rowLine {
    display:flex; 
    flex-direction:row;
}

And I changed the HTML to look like this:

<div className='rowLine'>
    <label>Search</label>
    <input type='text'/>
    <SimpleButton buttonAction={props.searchAction} buttonLabel="Search" />            
</div>

That worked, and I copied most of it from here. So now I’ve updated my CV to “Senior Front End Developer”.

It then occurred to me that, as good as this looks, there’s probably something in Bootstrap, and if there is, then my web page can look like the rest of the internet. It turns out I was right:

<div className="form-group row">
    <label htmlFor="searchText" className="col-sm-2 col-form-label">Search</label>
    <div className="col-sm-8">
        <input id="searchText" className="form-control" type='text'
                    placeholder="e.g. Goats" />
    </div>
    <div className="col-sm-2">
        <SimpleButton buttonAction={props.searchAction} buttonLabel="Search" />            
    </div>
</div>        

You may notice that React has its own “for” property, called “htmlFor”.

Disclaimer / Apology

As usual, please take everything you read in my blog with a healthy dose of salt. If you are a front end developer then please take solace in the fact that, despite me being facetious, I really need frameworks like Bootstrap, because I would never think to change the colour of a button, or to align the sizes.

This was all so much simpler in the days of Turbo Pascal / Turbo C, where you would draw your buttons using the ANSI character set!

References

https://stackoverflow.com/questions/39702130/line-two-divs-side-by-side-with-css-and-react

https://stackoverflow.com/questions/39187722/error-ts2339-property-for-does-not-exist-on-type-htmlpropshtmllabelelement

https://www.tutorialrepublic.com/twitter-bootstrap-tutorial/bootstrap-forms.php

Moving to Typescript with React

Typescript gives you a number of nice little statically typed features, which Javascript is sadly lacking. However, looking online, most of the tutorials and references use Javascript. This is a handy little post to allow you (or me) to use Typescript; or to use Javascript, and then transition to Typescript. Since you can use both in your project, you might find that migrating files one at a time allow you to gradually transition your code-base.

File name

When you create your first React app, you get a, by now, pretty standard SPA app. The entire app is running Javascript. To change one of the files over to Typescript, simply change the extension:

You now have your first Typescript component… Now the errors begin!

Props

Parameter ‘props’ implicitly has an ‘any’ type, but a better type may be inferred from usage.ts(7044)

This warning appears when you have the following constructor:

constructor(props) {  

Now that you’ve moved from a dynamic to a statically* typed language, Typescript is simply suggesting that you may have a better type than the Any** type that is assigned by default.

The easiest, and best transition here is simply to tell Typescript the type; for example:

interface IProps {
}

export class Home extends Component<IProps> {

  constructor(props: IProps) {    

If you actually have any properties, then you’ll need to include them in your interface; for example:

interface IProps {
  myValue: boolean
}

State

In Javascript, you define state by usage in the constructor; for example:

export class FetchData extends Component {
  static displayName = FetchData.name;
  constructor(props) {
    super(props);
    this.state = { forecasts: [], loading: true };
  }

Again, you need to define what the structure of state is:

interface IState {
  forecasts: string[];
  loading: boolean;
}

Then, you can reference that in the constructor, and pass the type into the base component:

export class Home extends Component<IProps, IState> {

  constructor(props: IProps, ) {    
    super(props);
    this.state = { 
      forecasts: [], 
      loading: true 
    };
  }

External Interface Files

One of the consequences of declaring these interfaces, is that you’ll quickly find that you need to reference the same interface from more than one place. For example, you may read some data in one component, and then display it in another. You could simply redeclare the interface in both places, but that feels dirty.

To get around this, you can simply declare a set of interfaces in a single file, or set of files. In C#, I would declare a single interface per file, so I’m tempted to lean towards this approach:

This doesn’t necessarily apply to any interfaces that are relevant to only a single component (for example, the interface for the props – unless they are shared – feels like it’s perfectly happy in the same file as the component).

Raising Events

In the same way as you now have to define what props look like, when you raise an event, you need to define what the event looks like; that is, you must tell Typescript the event type that you’re handling.

interface SearchProps {
    searchText: string;
    searchAction: (e: React.MouseEvent<HTMLButtonElement>) => void;
}
function Search(props: SearchProps) {
    
    return (
        <div>
            <label>Search</label>
            <textarea>{props.searchText}</textarea>
            <button onClick={props.searchAction}>Search</button>
        </div>
    );
}
export default Search;

External Libraries

If you’re referencing an external library, you may not have the Typescript definitions; let’s take reactstrap for example:

Could not find a declaration file for module ‘reactstrap’. ‘c:/myproject/ClientApp/node_modules/reactstrap/dist/reactstrap.cjs.js’ implicitly has an ‘any’ type.

Try `npm install @types/reactstrap` if it exists or add a new declaration (.d.ts) file containing `declare module ‘reactstrap’;`ts(7016)

You should be able to simply install this – which, in fact, it tells you to do in the error message:

npm install @types/reactstrap

References

https://stackoverflow.com/questions/46987816/using-state-in-react-with-typescript/46987987

Notes

* I’m not convinced that Typescript qualifies as a true statically typed language, rather it provides static typing for a dynamically typed language.

** Any is Typescript’s way of allowing you to revert to JavaScript, and just not type a specific variable; this is why I have doubts as to whether Typescript can be considered statically typed.

React Tips: 5 – Raising Events

Raising an Event is an interesting concept is React: essentially, you pass a function into a component; and then, when the component handles an event, it simply calls the function handler. This is referred to as “Raising” the event, because despite the event happening in the component, it is dealt with by a parent of that component. In C#, you would refer to this as a delegate, and in C, this would be passing a pointer to a function.

Here’s a component:

function MyComponent(props) {
    
    return (
        <div>
            <label>Change the text below</label>
            <input type='text' onChange={props.onChange} />
        </div>
    );
}
export default MyComponent;

If you look at that code, you’ll see that the onChange event is handled by a function passed in, called onChange. Here’s the calling component:

export class Home extends Component {

  render () {
    return (
      <div>
        <MyComponent onChange={this.onChange} />
      </div>
    }

The onChange function in Home will be called whenever the MyComponent textbox is changed.

Important Note

Since this is React, one of the things that you may do in the onChange function is to update the state. I have previously written on how to deal with this, or indeed any method which uses the this property.

Creating a Car Game in React – Part 6 – Adding High Scores

This is the sixth post of a series that starts here.

As with previous posts, if you wish to download the code, it’s here; and, as with previous posts, I won’t cover all the code changes here, so if you’re interested, then you should download the code.

In this post, we’re going to create a High Score table. We’ll create an Azure function as the server, and we’ll store the scores themselves in Azure Tables.

Let’s start with the table.

Create a new storage account in Azure, then add an Azure Table to it:

You’ll see a sign trying to persuade you to use Cosmos DB here. At the time of writing, using Cosmos was considerably more expensive than Table Storage. Obviously, you get increased throughput, distributed storage, etc with Cosmos. For this, we don’t need any of that.

Create a new table:

An Azure table is, in fact, a No SQL offering, as you have a key, and then an attribute – the attribute can be a JSON file, or whatever you choose. In our case, we’ll set the key as the user name, and the score as the attribute.

Once you’re created your table storage, you may wish to use the Storage Explorer to create the tables, although that isn’t necessary.

Finally, you’ll need to add a CORS rule:

Obviously, this should actually point to the domain that you’re using, rather than a blanket ‘allow’, but it’ll do for testing.

Adding a username

Before we can store a high score, the user needs a username. Let’s add one first.

In game status, we’ll add a text box:

<div style={containerStyle}>
	<input type='text' value={props.Username}
	onChange={props.onChangeUsername} />
</div>

The state is raised to the main Game.jsx:

<GameStatus Lives={this.state.playerLives} 
	Message={this.state.message} 
	Score={this.state.score} 
	RemainingTime={this.state.remainingTime}
	Level={this.state.level}
	Username={this.state.username} 
	onChangeUsername={this.onChangeUsername.bind(this)} 
/>

And onChangeUsername is here:

onChangeUsername(e) {
	this.updateUserName(e.target.value);
}

updateUserName(newUserName) {
	this.setState({
		username: newUserName
	});
}

Update High Score

We’ll create an Azure Function to update the table. In Visual Studio, create a new Windows Azure Function App (you will need to install the Azure Workload if you haven’t already):

You’ll be asked what the trigger should be for the function: we’ll go with HttpTrigger. This allows us to call our function whenever we please (rather than the function, being say scheduled.) Next, we’ll need to install a NuGet package into our project to let us use the Azure Storage Client:

Install-Package WindowsAzure.Storage

We need some access details from Azure:

Creating the Functions

We’re actually going to need two functions: update and retrieve (we won’t be using the retrieve in this post, but we’ll create it anyway). Let’s start with a helper method:

    public static class StorageAccountHelper
    {
        public static CloudStorageAccount Connect()
        {
            string accountName = Environment.GetEnvironmentVariable("StorageAccountName");
            string accountKey = Environment.GetEnvironmentVariable("StorageAccountKey");

            var storageAccount = new CloudStorageAccount(
                new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
                    accountName, accountKey), true);
            return storageAccount;
        }
    }

For testing purposes, add the account name and key into the local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "StorageAccountName": "pcmtest2",
    "StorageAccountKey": "C05h2SJNQOXE9xYRObGP5sMi2owfDy7EkaouClfeOSKRdijyTQPh1PIJgHS//kOJPK+Nl9v/9BlH4rleJ4UJ7A=="
  }
}

The values here are taken from above – where we copied the access keys from Azure (whilst these keys are genuine keys, they will be changed by the time the post is published – so don’t get any ideas!

First, let’s create a function to add a new high Score:

        [FunctionName("AddHighScores")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var newScore = new HighScore(req.Query["name"], int.Parse(req.Query["score"]));            

            var storageAccount = StorageAccountHelper.Connect();

            CloudTableClient client = storageAccount.CreateCloudTableClient();
            var table = client.GetTableReference("HighScore");

            await table.ExecuteAsync(TableOperation.InsertOrReplace(newScore));

            return new OkResult();
        }

If you’ve seen the default example of this function, it’s actually not that different: it’s a POST method, we take the name and score parameters from the query string, build up a record and add the score. The function isn’t perfect: any conflicting names will result in overwritten score, but this is a copy of a spectrum game – so maybe that’s authentic!

The second function is to read them:

        [FunctionName("GetHighScores")]
        public static async Task<IList<HighScore>> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            var storageAccount = StorageAccountHelper.Connect();

            CloudTableClient client = storageAccount.CreateCloudTableClient();
            var table = client.GetTableReference("HighScore");
            var tq = new TableQuery<HighScore>();
            var continuationToken = new TableContinuationToken();
            var result = await table.ExecuteQuerySegmentedAsync(tq, continuationToken);
            
            return result.Results;
        }

All we’re really doing here is reading whatever’s in the table. This might not scale hugely well, but again, for testing, it’s fine. The one thing to note here is ExecuteQuerySegmentedAsync: there seems to be very little documentation around on it; and what there is seems to refer to ExecuteQueryAsync (which, as far as I can tell, doesn’t, or at least, no longer, exists).

Let’s run the Azure function locally and see what happens:

As you can see, Azure helpfully gives us some endpoints that we can use for testing. If you don’t have a copy already, then download Postman. Here you can create a request that calls the function.

I won’t go into the exact details of how Postman works, but the requests might look something like this:

http://localhost:7071/api/AddHighScores?name=test2&score=19
http://localhost:7071/api/GetHighScores?10

To prove to yourself that they are actually working, have a look in the table.

There is now an online Storage Explorer in the Azure Portal. Details of the desktop version can be found in this post.

Update High Score from the Application

Starting with adding the high score, let’s call the method to add the high score when the player dies (as that’s the only time we know what the final score is):

playerDies() { 
    this.setState({
        playerLives: this.state.playerLives - 1,
        gameLoopActive: false
    });

    if (this.state.playerLives <= 0) {
        this.updateHighScore();
        this.initiateNewGame();
    } else {
        this.startLevel(this.state.level);
    }

    this.repositionPlayer();
    this.setState({ 
        playerCrashed: false,
        gameLoopActive: true
    });
}

The updateHighScore function looks like this:

updateHighScore() {
	fetch('http://localhost:7071/api/AddHighScores?name=' + this.state.username + '&score=' + this.state.score, {
		method: 'POST'
	}); 
}

Note (obviously) that here I’m updating using my locally running instance of the Azure Function.

And that’s it – we now have a score updating when the player dies. Next we need to display the high scores – that’ll be the next post.

References

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

https://facebook.github.io/react-native/docs/network

React Tips: 4 – Propagating State

One thing that’s worth remembering about React is that when you’re updating state, only the Render method gets re-executed.

It’s easy (as I did) to fall into the trap of doing something like this:

    const myStyle = {
        background: this.props.backgroundFlag == 1 ? "blue" : "yellow",
        display: 'inline-block',
        height: '100%',
    }

    public render() {
        return <>
            <div className="myDiv" style={myStyle}>
        </>
    }

Imagine that this.props.backgroundFlag is actually the state of the containing component; when you change it, you would expect your component to reflect your change. However, in the case above, what will actually happen is nothing – because only the render method is re-evaluated when the virtual DOM changes.

To correct this, you need whatever needs to be re-evaluated inside the render method; for example:

    public render() {
	    const myStyle = {
	        background: this.props.backgroundFlag == 1 ? "blue" : "yellow",
	        display: 'inline-block',
	        height: '100%',
	    }

        return <>
            <div className="myDiv" style={myStyle}>
        </>
    }

React Tips: 3 – Cloning a React Repository

After you clone a React repository, running npm start may give this error:

‘react-scripts’ is not recognized as an internal or external command

The reason, as explained here, is that you need to run:

npm install

This should be run inside the directory that you clone. For example:

git clone https://github.com/pcmichaels/react-demos.git
cd react-demos
npm install
npm start

React Tips: 2 – Binding an Event Handler

Example code here.

When dealing with any flavour of Javascript, sooner or later, you’re going to come across the this problem. The issue being that, what this means, depends on where you are. This can be a particularly prevalent issue with React; imagine the following code:

onMouseUp={this.onMouseUp}

In onMouseUp, you might want to affect the state in some way:

private onMouseUp(e) {
    this.setState({
        dragging: false
    });

If you run this, you’ll likely get the following error:

TypeError: this is undefined

I think you’ll agree, a clearer message couldn’t be had.

Binding

The answer to the problem that I’ve so eloquently posed here, is binding. Essentially, you simply tell your local function to know about this:

onMouseUp={this.onMouseUp.bind(this)}

This does fix the problem; now the method will execute without error. However, what we are actually doing here is creating a new function every time the page is rendered. To circumvent this you can leave the original code as it was:

onMouseUp={this.onMouseUp}

But then bind the method in the constructor:

constructor(props) {
    super(props);

	this.onMouseUp = this.onMouseUp.bind(this);

As an aside, if you happen to see the following error:

Argument of type ‘this’ is not assignable to parameter of type ‘MouseEvent‘.

You’ve likely missed the .bind; for example:

this.onMouseUp = this.onMouseUp(this);

Ask me how I know!

Class Properties

Another, newer (and IMHO much cleaner), way around this is the following syntax:

onMouseDown = (e) => {
    console.log('onMouseDown');
    this.setState({
        dragging: true
    });
}

This doesn’t require any binding.

References

https://reactjs.org/docs/faq-functions.html