We will now get started on the frontend for our C# .Net Core application.

Photo by Tianyi Ma on Unsplash

Here is the first part of the tutorial for reference or if you haven’t started this part yet which I would recommend.

We will initialize our webpack project using webpack cli. We will first delete everything in the wwwroot folder, then do a npm init which will create a package.json.

cd source/repos/Games/Games.Web/wwwroot
npm init -y

Then we will install these devDependencies first. That will configure our frontend project.

npm i -D webpack webpack-cli webpack-dev-server @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loader html-webpack-plugin prop-types

— Webpack Dependencies

webpack-Used to bundle your files in your dist or public folder(or distribution/production) folder in a file called index.bundle.js in the dist folder in this tutorial.

webpack-cli-Used to perform webpack commands within your terminal if needed, and will be used if you want to build your app for production.

webpack-dev-server-Used after your files are bundled, to enable hot reloading(have your file rebundled anytime you make changes), and have it open upon npm start.

css-loader-Bundles css.

style-loader-Adds css access to the dom using styles tags, and webpack.

html-webpack-plugin-Simplifies the creation of html files to handle your webpack bundles.

— Babel Dependencies

@babel/core-Will be used to transpile es6 code to es5, to your local configuration files.

@babel/preset-react-Will compile jsx to javascript code.

@babel/preset-env-Will compile es6 to es5 code.

babel-loader-Allows for transpiling of es6 and jsx to es5 javascript using babel and webpack.

— Other Dependencies for cleaner code

prop-types-Enables the use of passing requirements to our props, therefore having more organized and concise code. (NOTE: Can also import PropTypes from react)

Now install these couple of dependencies for creating the application which would be general dependencies.

npm i -S react react-dom react-router history connected-react-router react-redux redux

— React Dependencies

react-Javascript library for creating user interfaces (Note: It is not a framework!!)

react-dom-The virtual dom itself, which will update parts of the HTML that needs to be updated instead of the whole page.The entry point for the dom and server.

— Redux Dependencies

react-router-Define your routes.

history-Allows to manage history anywhere javascript runs. Will be used with our connected-react-router.

connected-react-router-Contains our routes which would be in a routerReducer, and will be in the store.(Does redux binding to react-router v4 api.) Here is the documentation.

react-redux-Responsible for connecting react components to redux store.

redux-Responsible for configuring your redux store.

Now create a .babelrc file with just a property of presets, and it being set to preset-env, and preset-react.

touch .babelrc
Configure your babel configuration file, with your @babel/preset-env and @babel/preset-react dev dependencies.

Now create a webpack.config.js file which will contain our configurations options in a form of an object.

touch webpack.config.js

We will first import our path module for joining paths, and our html-webpack-plugins to have a specific html file(index.html) be a template for our bundled html file in our dist folder.

Then we will have a module.exports which would be assigned to an object that will contain 5 properties entry, output, devServer, module, and plugins.

entry-Entry point of application.

output-The name of our bundled file, and where it would be.

devServer-Extra options to the webpack-dev-server, which will be used to configure our routing.

module-Rules for our loader, and what loader to use for each rule.

plugins-Adds any extra features you would want to be implemented while bundling your files.

Define your webpack configuration file, with your entry, output, module, and plugins property.

Then afterwards create a src folder, then within the src folder create a styles and components folder. Also create a index.js, and a index.html file, both being the entry point and template for your application.

mkdir src
cd src
mkdir components styles
touch index.js index.html

Then within the components and styles folder create a App.js and a App.css.

cd components 
touch App.js
cd ..
cd styles
touch App.css

Now your file structure should look like this.

Screenshot of file structure.

In our index.html have html 5 markup then have a div tag within the body with an id of root, where the virtual dom would be rendered. Also add a base tag which would be your base url set to the href attribute.

Define your index file for development.

Then in our index.js file import react, react-dom and App component. Then pass your App component as a first argument, then your root selector as your second argument. In order to render your application.(NOTE: Your App component is not defined yet.)

Define the index.js file which would be responsible for rendering your application.

Now in your App.js have it be just a class component with no props, and have it just have a title with Games App. Also import our styles from our App.css, and set our divs with a className of container be a color of green, and background-color of white in our App.css file.

Define your App component.
Define your styles for your App component.

Now we will edit our package.json, and add 2 property to our scripts property. There will be a start and build property. The start property which would be how the dev server is started. The build property is how the production server is started.

Define your build and start property.

Now run npm start to bundle all your files. Now your files are bundled, so replace the start script for development with your webpack dev server with a hot flag, which enables hot reloading. Then also add a open flag which will open the app once the files is bundled.

Replace your webpack start script with your webpack-dev-server start script.

Now your app should look like this.

Startup your application.

Now we will start setting up our project where we would define our components. We will create two folders in the components folder, which will be presentational and container folders.

cd components && mkdir presentational container

presentational-Means components that are meant to display data, and are most of the time functional components.

container-Means component that are meant to display presentational components, and perform side effects such as fetching data.

We will first start creating our components in the presentational folder, which would be our Navbar and GameItem component.

cd presentational && touch Navbar.js GameItem.js && cd ..

Navbar-Will be displaying on every component, and will be used to navigate to different routes.

GameItem-Will display each individual game item that retrieved via the fetch calls .

Now we will create a Navbar.css and a Games.css within our styles folder.

cd styles && touch Navbar.css Games.css && cd ..

Navbar.css-WIll be the styles of the navbar.

Games.css-Will be the styles of all Game related components.

Great! Now we will start creating our container components. Which would be Home, Games, GamePage, and CreateGame.

cd container && touch Home.js Games.js GamePage.js CreateGame.js && cd ..

Home-Will be just a placeholder component in a sense meant to render your initial route(which we will define later in the tutorial.)

Games-Will render your all your Games which will render the GameItem component, and when you click the GameItem component it will navigate the user to the GamePage.

GamePage-Will render info for each individual game.

CreateGame-Will be responsible for creating each game via a post http request.

Now before we define our components, lets setup our redux directories. We will create a redux folder with a store and reducer file.

mkdir redux && cd redux && touch store.js reducer.js 

store-Define your store, and your middleware from connected-router.

reducer-Define your reducer which would be used to manipulate the global state and in this case it will be where all our state is stored in this tutorial.

Define your reducer.js file which will contain.

initialState-Will be where our default redux state will be, it would be manipulated via the reducer function in the same file or can be different files also just need to import it to that file.

action types-Will be constant variables for each action type used in the reducer or returned/dispatched from a action.

actions-Will be functions that will manipulate the redux state via returning a object with a type and optionally a payload if you want to assign data to the state(which we will do).

reducer-Will be a function that will be solely responsible for manipulating the redux via the action.type using a switch statement, with the initialState being the default value, and return value. Then the action that would be used anytime a action is dispatched.

Now that is the basic walkthrough of what our reducer will contain, now our store will contain the store which will be created using the reducer in our reducer.js, and our routes via the routerMiddleware in connected-react-router. Which we would use applyMIddleware HOC(Higher Order Component-a function that returns a component will desired props) from redux to apply it to our store.

Now let’s start implementing it.

We will first define our initialState. Which will contain list for getting all the games. Then a currentGame when we render each individual game in our gamePage. Then a createGameForm which would be for creating a game.

Then define your action types which will be.

ASSIGN_LIST-For retrieving data and assigning to your list state.

CHANGE_CREATE_GAME_FORM-For handling input changes for your createGameForm.

GAME_CREATED-For assigning your currentGame state after your game is created.

ASSIGN_CURRENT_GAME-For assigning our currentGame state when we are routed to our GamePage component.

RESET_CURRENT_GAME-For when we get routed out of our GamePage component, to have the currentGame get set back to it’s initialState.

Then define our reducer function which will have two arguments with a state which by default will be assigned to the initialState, and our action. We will have a switch statement for our action.type, and based on that we will return a new state using Object.assign which will return a new object since we would want to treat the data as immutable.

Then last define our actions. They will be 5 at the moment.

getGames-Takes a games argument, and returns a object with a type of ASSIGN_LIST, and a payload of the games argument.

getGame-Takes a game argument, and returns a object with a type of ASSIGN_CURRENT_GAME, and a payload of our game argument.

resetGame-That just returns a object with a type of RESET_CURRENT_GAME and reset’s currentGame to it’s initial state.

changeCreateGame-That takes a form argument, and returns a object with a type of CHANGE_CREATE_GAME_FORM and payload of form.

gameCreated-That takes a game argument, and returns a object with a type of GAME_CREATED and a payload of game.

Define your reducer.

Now define your store. We will first import createStore, and applyMiddleware from redux. Then import your createBrowserHistory from history module for your routerMiddleware, and your Router history in your index.js(we will configure later in this tutorial) from connected-react-router. Then import routerMiddleware from connected-react-router. Then import your reducer.

Then export assign a variable called history with your createBrowserHistory function invoked defining history, also export since we will use it in the index.js.

Then define your reactRouterMiddleware with your routerMiddleware with your history variable as argument to be used in applyMiddleware.

Then create your store using the createStore function from redux, with your reducer, and a applyMiddleware with your routerMiddleware as a argument.

Define your store.

Now to top if all off. Go to your index.js and import your Provider component from react-redux, and your Router component from connected-react-router. Also import your history variable, and your store from your store.js file.

We will nest your App with your Provider component with a store prop set to your store, and your Router component with a history prop set to your history variable.

Define your index.js with your App component configure to redux and connected-react-router.

Now our app is configure to redux, now let’s configure our app so we can get all the games .

But before fetching data from our server, define a static class that is responsible for adding sample data to your mysql database. If the context does not contain any instances of the Game class then seed our db with sample data.(NOTE: Add this static class to the Games.Data/Seeds folder)

Define static class responsible for seeding data to your database.

Then we will first change our Startup.cs file to get the data we would need to retrieve. We will first make our server use cors just for good measure, and make our server secure. Then allow any origin, header, and method, and pass your context to be used at runtime to seed your mysql database with sample data. Also for your ConfigureServices function add cors to your project. (NOTE: Also reference your Static class responsible for seeding data.)

Seed data at runtime.

Define your Home Component.

Define your Home component which render a game controller and header text.

For your GameList, CreateGame, GamePage with basic html.

Define basic GameList component.
Define your Basic CreateGame component.
Define your basic Game Component.

The reason we defined our components with very basic html is because we want to define our routes, and make our routes are working correctly.

Now let’s start defining our Routes by importing our Route component for each individual route, and Switch component which renders the first component that matches the current location.

Define your routes.

Define your navbar that will be existent on every component, and render on the app component. The navbar will take a goToRoute method that will be defined in the app.js. It will take a elements props which would be the links. It will contain a label which would be the link of the label, and a path which would be the route.

Define the Navigation bar.

Then add a couple finishing touches to your Navbar styling.

Define Navbar.css file for styling.

Define a method that will be responsible routing the user via the history prop from react-router. It push to that history object, therefore should route the user.

Import your Navbar component and define method for routing in App.js

Now you should see the GameList component, now let’s define our GameItem component which would be responsible for rendering each individual game in the GameList component.

Define component responsible for rendering each individual game.

Define GameItem styles, in the Games.css file.

Define games.css file.

Now let’s finish this part, by fetching data. In the GameList component, we will add a constructor, initialize state with list property, and in our componentDidMount(lifecycle method after the component mounts). We will use fetch api to fetch data, and pass a Request object with a url, and options. Pass api of server as uri, and set options to method Get, type is application/json, and set it’s mode to cors.

Then render the list conditionally just for good measure.

Now our list is rendered.

Resulting GameList component.

Now connect the component to the redux store,import bindActionCreators which will bind the actions imported from the reducer to the dispatcher(responsible for dispatching actions therefore updating initial redux state.). Then import the connect from react-redux connecting the component to redux. Then import prop-types to return warning’s if the props passed to GameList component does not follow the prop-types. It’s similar to a interface in C#.

Define the MapStateToProps that will map the initial redux state to the component props. Then define the mapDispatchToProps, we will first define a new object with our action as a property. Then return a object with a actions property set to the bindActionCreators with our actions, and dispatch.

Finish GameList component.

Now when you route to the GamePage component, just have the info be rendered, via fetch to your server url that will retrieve that individual game information, and connect it to redux. We will use our react-router’s match.params prop, and retrieve the id parameter which was the name of the parameter that’s in the routes.js file for that current route.

Then a brief introduction to componentWillUnmount, also reset your redux state to prevent rendering previous game, and to prevent memory leaks.

Define your GamePage component.

We are finished getting data. Let’s get start creating data via a post request.

Now let’s define the page responsible for creating Games. It will be a form and it will be connected to redux. Import changeCreateGame, and gameCreated actions to be binded to actions props via the mapDispatchToProps. It will have a handleChange method, and a createGame method. The handleChange will be responsible for handling changes for the input. Which is connected to our redux store. Then createGame will assign the currentGame state to the new game created. (NOTE: Import similar entities found in other components connected to redux)

First define styles for your form in the Games.css

Define styles for your CreateGame component.

When we fetch our data pass a new Request object with the uri of our C# server, and pass options. Our options will contain a method of POST, type of application/json, headers with a Content-Type header of application/json, a body with our object converted to a string via JSON.stringify, and set it’s mode to cors since our server is cors.

Define component responsible for creating games.

Now type anything to your form and click submit, and it should create the new game.

Our sample data

Now you should be redirected to your GameList component and see your new game, and when clicking on each game you should be redirected to new screen.

So we have finished most of our tutorial. The next part is focused updating and deleting games.

Here is my github for reference:

Here is the first part also:

Happy Coding!