React and C# Basic Tutorial for Beginners: Build Your First Full Stack Web Application
If you are a C# developer who wants to learn modern frontend development, React is one of the most practical technologies to explore.
React can handle the interactive frontend of your application, while C# and ASP.NET Core can power the backend API, business logic, authentication, validation, and database operations.
Together, these technologies can be used to build modern full stack applications such as dashboards, inventory systems, e-commerce platforms, SaaS products, customer portals, and business management applications.
In this beginner-friendly React and C# tutorial, you will learn how React works, how it communicates with an ASP.NET Core Web API, how data moves between the frontend and backend, and how you can structure a small application using React, C#, Entity Framework Core, and a relational database.
The goal is not to cover every React feature. Instead, we will build a practical foundation that you can use to create more advanced full stack applications.
What Is React?
React is a JavaScript library for building user interfaces.
It allows developers to create reusable UI components and combine them to build interactive applications.
Instead of treating an entire page as one large block of HTML and JavaScript, React encourages you to divide the interface into smaller components.
For example, a business application might contain:
Header
Sidebar
Dashboard
ProductList
ProductForm
CustomerList
SalesReportEach part can be developed and maintained as a separate component.
React is commonly used for:
Business applications
SaaS platforms
E-commerce websites
Dashboards
Customer portals
Inventory applications
Administrative interfaces
Interactive websites
In a React and C# application, React is normally responsible for the frontend user interface.
What Is C#?
C# is a modern, strongly typed programming language developed by Microsoft.
It is widely used for:
Web applications
REST APIs
Desktop applications
Cloud services
Enterprise systems
Background services
Integrations
For modern web development, C# is commonly used with ASP.NET Core.
ASP.NET Core can handle:
REST APIs
Business logic
Authentication
Authorization
Validation
Database communication
Background processing
External integrations
A simple way to understand the responsibilities is:
React
↓
Frontend
ASP.NET Core + C#
↓
Backend
Database
↓
Persistent DataReact and C# therefore solve different parts of the same application.
How React and C# Work Together
React and C# usually communicate through HTTP APIs.
Consider a product management application.
When a user opens the product page, React can send a request to the ASP.NET Core API:
GET /api/productsThe backend retrieves the products and returns a JSON response:
[
{
"id": 1,
"name": "Laptop",
"price": 75000
},
{
"id": 2,
"name": "Keyboard",
"price": 2500
}
]React receives the JSON data and renders it in the browser.
The complete flow looks like this:
User
↓
React Application
↓
HTTP Request
↓
ASP.NET Core Web API
↓
Business Logic
↓
Entity Framework Core
↓
DatabaseThe response travels back in the opposite direction:
Database
↓
ASP.NET Core
↓
JSON Response
↓
React
↓
User InterfaceUnderstanding this request and response flow is one of the most important steps in learning React with C#.
What Should You Know Before Learning React?
You do not need to be an expert frontend developer before starting React.
However, some basic knowledge will make the learning process much easier.
HTML
HTML defines the structure of a web page.
<h1>Products</h1>
<button>Add Product</button>CSS
CSS controls the visual presentation of the application.
You will use CSS for:
Layout
Colors
Spacing
Typography
Responsive design
Animations
JavaScript
JavaScript knowledge is particularly important for React.
Before going deeply into React, become comfortable with:
Variables
Functions
Objects
Arrays
Array methods
Destructuring
Modules
Promises
Async and await
TypeScript
React applications can be developed using JavaScript or TypeScript.
For C# developers, TypeScript can feel more familiar because it supports static typing, interfaces, generics, and other type-related features.
In this tutorial, we will use TypeScript because it gives us clearer contracts between the frontend and backend.
Creating a React Application
A modern React application can be created using a build tool such as Vite.
Run:
npm create vite@latest react-csharp-demoChoose React and TypeScript when prompted.
Move into the project:
cd react-csharp-demoInstall the dependencies:
npm installStart the development server:
npm run devThe terminal will show the local URL where the application is running.
You now have a basic React application ready for development.
Understanding React Components
Components are at the heart of React development.
A component represents a reusable part of the user interface.
function ProductList() {
return <h2>Product List</h2>;
}
export default ProductList;You can use this component inside another component:
import ProductList from './ProductList';
function App() {
return (
<div>
<h1>Inventory Application</h1>
<ProductList />
</div>
);
}
export default App;This component-based approach helps divide a large application into smaller and more manageable pieces.
Understanding JSX
React components commonly use JSX.
JSX allows you to write markup-like syntax inside JavaScript or TypeScript code.
function Welcome() {
const name = 'John';
return <h2>Welcome, {name}</h2>;
}The browser will display:
Welcome, JohnValues inside {} are evaluated as JavaScript expressions.
JSX looks similar to HTML, but there are some differences.
For example, CSS classes use className:
<div className="product-card">
Product
</div>Understanding JSX is essential because you will use it throughout React development.
Passing Data with Props
React components often need to receive information from other components.
React uses props for this purpose.
type ProductProps = {
name: string;
price: number;
};
function Product({ name, price }: ProductProps) {
return (
<div>
<h3>{name}</h3>
<p>Price: {price}</p>
</div>
);
}You can use the component like this:
<Product
name="Laptop"
price={75000}
/>Props make components reusable.
The same component can display many products without duplicating the UI code.
Understanding State in React
Some application data changes while the user interacts with the page.
React uses state to manage this kind of data.
The useState hook is commonly used for local component state.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increase
</button>
</div>
);
}Here, count contains the current value and setCount updates it.
When the state changes, React updates the relevant UI.
State is commonly used for:
Form values
Search text
Selected items
Loading indicators
API results
Dialog visibility
Pagination
Handling Events in React
React applications need to respond to user actions.
function ProductButton() {
const handleClick = () => {
alert('Product selected');
};
return (
<button onClick={handleClick}>
Select Product
</button>
);
}React can handle browser events such as:
Click
Change
Submit
Focus
Keyboard input
You will use events extensively when building forms and interactive interfaces.
Creating the C# Backend
Now let's create the backend of our application.
Suppose we want to manage products.
A simple C# entity can look like:
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}Initially, you can use an in-memory collection to understand the API flow.
Later, we will connect the same application to a database.
Creating an ASP.NET Core API Controller
A basic controller might look like:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult GetProducts()
{
var products = new List<Product>
{
new Product
{
Id = 1,
Name = "Laptop",
Price = 75000
},
new Product
{
Id = 2,
Name = "Keyboard",
Price = 2500
}
};
return Ok(products);
}
}The endpoint is:
GET /api/productsWhen React calls this endpoint, ASP.NET Core returns the collection as JSON.
Creating a Product Type in React
Because we are using TypeScript, we can describe the API response with an interface.
export interface Product {
id: number;
name: string;
price: number;
}This helps TypeScript understand the expected structure of the API data.
It also improves editor support and catches some mistakes during development.
Configure the API URL with Vite Environment Variables
Hard-coding API URLs inside components makes configuration harder when moving between development, staging, and production environments.
Instead of writing this throughout the application:
https://localhost:7001/api/productscreate a .env file:
VITE_API_URL=https://localhost:7001Access it using:
const apiUrl = import.meta.env.VITE_API_URL;Then build the endpoint:
const productsUrl = `${apiUrl}/api/products`;For a real project, you may use separate environment configurations for local development and deployed environments.
Frontend environment values are included in client-side application code. Never put passwords, private API keys, database connection strings, or other secrets in a React environment variable.
Calling the ASP.NET Core API from React
The browser provides the fetch API for HTTP communication.
A simple request looks like:
const response = await fetch(
`${import.meta.env.VITE_API_URL}/api/products`
);
const data = await response.json();For a small demonstration, calling fetch directly from a component is easy to understand.
As an application grows, moving API communication into a dedicated service keeps components cleaner.
Creating a Product API Service
Create:
src/services/productService.tsThen add:
import type { Product } from '../models/Product';
const apiUrl = import.meta.env.VITE_API_URL;
export async function getProducts(): Promise<Product[]> {
const response = await fetch(`${apiUrl}/api/products`);
if (!response.ok) {
throw new Error('Unable to load products');
}
return response.json();
}Now the component does not need to know all the details of the HTTP request.
The structure becomes:
ProductList
↓
productService
↓
ASP.NET Core APIThis becomes more useful as you add create, update, delete, authentication, and other API operations.
Loading Products with useEffect
Now we can use the service inside a component.
import { useEffect, useState } from 'react';
import type { Product } from '../models/Product';
import { getProducts } from '../services/productService';
function ProductList() {
const [products, setProducts] = useState<Product[]>([]);
useEffect(() => {
const loadProducts = async () => {
const data = await getProducts();
setProducts(data);
};
loadProducts();
}, []);
return (
<div>
<h2>Product List</h2>
</div>
);
}
export default ProductList;useEffect is useful here because loading remote data is a side effect associated with the component.
For larger applications, you may eventually use more specialized data-fetching approaches. For a beginner project, understanding fetch, state, and effects first gives you a useful foundation.
Displaying API Data
Once the products are stored in state, display them using map():
return (
<div>
<h2>Product List</h2>
<ul>
{products.map(product => (
<li key={product.id}>
{product.name} - {product.price}
</li>
))}
</ul>
</div>
);The result might look like:
Product List
Laptop - 75000
Keyboard - 2500At this point, you have created the core full stack flow:
React
↓
Service
↓
HTTP Request
↓
ASP.NET Core
↓
JSON Response
↓
React State
↓
User InterfaceHandling Loading and API Errors
A real application should not assume that every request succeeds instantly.
Add loading and error state:
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);Then:
useEffect(() => {
const loadProducts = async () => {
try {
const data = await getProducts();
setProducts(data);
} catch {
setError('Unable to load products. Please try again.');
} finally {
setLoading(false);
}
};
loadProducts();
}, []);The UI can respond accordingly:
if (loading) {
return <p>Loading products...</p>;
}
if (error) {
return <p>{error}</p>;
}This provides a better user experience than displaying an empty screen when something goes wrong.
Understanding CORS
During development, React and ASP.NET Core often run on different origins.
For example:
React
http://localhost:5173and:
ASP.NET Core
https://localhost:7001Configure ASP.NET Core:
builder.Services.AddCors(options =>
{
options.AddPolicy("ReactPolicy", policy =>
{
policy
.WithOrigins("http://localhost:5173")
.AllowAnyHeader()
.AllowAnyMethod();
});
});Enable the policy:
app.UseCors("ReactPolicy");Use the actual frontend origin configured for your application.
In production, avoid unnecessarily broad CORS policies.
Sending Data from React to C#
Suppose we want to create a product.
React can send a POST request:
export async function createProduct(product: {
name: string;
price: number;
}) {
const response = await fetch(
`${apiUrl}/api/products`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(product)
}
);
if (!response.ok) {
throw new Error('Unable to create product');
}
return response.json();
}ASP.NET Core can receive the request:
[HttpPost]
public IActionResult CreateProduct(CreateProductDto model)
{
// Validate and save product
return Ok(model);
}The flow becomes:
React Form
↓
Product Service
↓
POST Request
↓
ASP.NET Core
↓
Validation
↓
DatabaseWhy Use DTOs?
DTO stands for Data Transfer Object.
A DTO defines what information the API expects to receive or return.
public class CreateProductDto
{
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
}The controller can accept it:
[HttpPost]
public IActionResult CreateProduct(CreateProductDto model)
{
// Map DTO to entity and save
return Ok();
}DTOs help separate your API contract from your database entities.
That separation becomes increasingly valuable as the application grows.
React and C# CRUD Operations
CRUD stands for:
Create
Read
Update
Delete
A typical product API might contain:
| Operation | HTTP Method | Endpoint |
|---|---|---|
| Create | POST | /api/products |
| Read All | GET | /api/products |
| Read One | GET | /api/products/1 |
| Update | PUT | /api/products/1 |
| Delete | DELETE | /api/products/1 |
Once you understand this pattern, you can apply it to customers, employees, suppliers, categories, orders, inventory, and many other business entities.
Deleting a Product from React
Add a delete operation to the service:
export async function deleteProduct(id: number): Promise<void> {
const response = await fetch(
`${apiUrl}/api/products/${id}`,
{
method: 'DELETE'
}
);
if (!response.ok) {
throw new Error('Unable to delete product');
}
}The component can call it:
const handleDelete = async (id: number) => {
try {
await deleteProduct(id);
setProducts(current =>
current.filter(product => product.id !== id)
);
} catch {
setError('Unable to delete the product.');
}
};Add a button:
{products.map(product => (
<div key={product.id}>
<span>
{product.name} - {product.price}
</span>
<button onClick={() => handleDelete(product.id)}>
Delete
</button>
</div>
))}After the API successfully deletes the product, React removes it from the current UI state.
Connecting ASP.NET Core to a Database
The earlier API used an in-memory collection.
A real application normally stores products in a database.
ASP.NET Core can use Entity Framework Core for data access.
React
↓
ASP.NET Core Web API
↓
Application / Business Logic
↓
Entity Framework Core
↓
SQL Server / PostgreSQLA real asynchronous controller action could look like:
[HttpGet]
public async Task<ActionResult<List<Product>>> GetProducts()
{
var products = await _dbContext.Products
.ToListAsync();
return Ok(products);
}A delete endpoint could look like:
[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteProduct(int id)
{
var product = await _dbContext.Products
.FindAsync(id);
if (product is null)
return NotFound();
_dbContext.Products.Remove(product);
await _dbContext.SaveChangesAsync();
return NoContent();
}Now the frontend and backend are performing actual CRUD operations against persistent data.
React Forms
Forms are essential for most business applications.
import { useState } from 'react';
function ProductForm() {
const [name, setName] = useState('');
const [price, setPrice] = useState(0);
const handleSubmit = async (
event: React.FormEvent
) => {
event.preventDefault();
console.log({
name,
price
});
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={event =>
setName(event.target.value)
}
/>
<input
type="number"
value={price}
onChange={event =>
setPrice(Number(event.target.value))
}
/>
<button type="submit">
Save Product
</button>
</form>
);
}
export default ProductForm;Later, handleSubmit can call createProduct() from the API service.
Client-Side and Server-Side Validation
Validation should exist on both sides.
React can provide immediate feedback:
if (!name.trim()) {
setError('Product name is required');
return;
}However, frontend validation can be bypassed.
The backend must validate important input independently.
public class CreateProductDto
{
[Required]
public string Name { get; set; } = string.Empty;
[Range(0.01, double.MaxValue)]
public decimal Price { get; set; }
}A useful rule is:
React validation improves the user experience.
ASP.NET Core validation protects your application and data.
Never rely only on client-side validation.
React Routing
As an application grows, you will usually need multiple routes.
/
/login
/dashboard
/products
/products/10
/customers
/reportsRouting allows different URLs to display different parts of the application.
A business application might have pages for:
Dashboard
Products
Customers
Orders
Reports
SettingsRouting is worth learning after you understand components, props, state, and basic API communication.
Authentication Between React and ASP.NET Core
Most real applications require authentication.
A simplified flow looks like:
React Login Form
↓
ASP.NET Core API
↓
Validate Credentials
↓
Authentication Result
↓
React ApplicationProtected API requests then include the appropriate authentication information.
Remember:
Authentication asks: Who are you?
Authorization asks: What are you allowed to do?
For example, a user might be able to view products while only an administrator is allowed to delete them.
Authentication and authorization deserve their own detailed tutorial because application security should not be reduced to a small CRUD code sample.
A Practical React and C# Project Structure
A small React application might eventually look like:
src
│
├── components
├── pages
├── features
│ └── products
├── models
│ └── Product.ts
├── services
│ └── productService.ts
├── hooks
└── routesThe ASP.NET Core application might contain:
ASP.NET Core API
│
├── Controllers
├── DTOs
├── Entities
├── Services
├── Data
├── Validation
└── ConfigurationThere is no single folder structure that is correct for every application.
The important goal is to keep responsibilities clear and make the project understandable as it grows.
A Good First React and C# Project
A Product Management System is an excellent beginner project.
Start with:
Product List
Product Details
Create Product
Edit Product
Delete ProductThen add:
Search
Filtering
Pagination
Validation
Loading States
Error HandlingNext, introduce:
SQL Server or PostgreSQL
Entity Framework Core
Authentication
Authorization
CategoriesOnce those features work, you can expand the same project into:
Customers
Suppliers
Purchases
Sales
Inventory
ReportsThis approach is useful because every new concept improves the same application instead of creating disconnected examples.
React and C# Learning Path for Beginners
If you are a C# developer starting React, follow a structured learning path.
Step 1: Learn Modern JavaScript
Focus on:
Variables
Functions
Arrays
Objects
Destructuring
Modules
Promises
Async and await
Step 2: Learn TypeScript Basics
Learn:
Types
Interfaces
Functions
Classes
Generics
Union types
Optional properties
Step 3: Learn React Fundamentals
Focus on:
Components
JSX
Props
State
Events
Conditional rendering
Lists
Forms
Step 4: Learn React Hooks
Start with:
useStateuseEffect
Learn additional hooks when your application actually requires them.
Step 5: Learn API Communication
Practice:
GET
POST
PUT
DELETE
Loading states
Error handling
Request cancellation where appropriate
Step 6: Learn ASP.NET Core Web API
Study:
Controllers
Routing
HTTP methods
DTOs
Validation
Dependency injection
Authentication
Authorization
Step 7: Learn Entity Framework Core
Focus on:
DbContext
Entities
Relationships
Migrations
LINQ
Async queries
Transactions
Step 8: Build a Complete Application
Combine the concepts into one project instead of learning each technology in isolation.
Common Mistakes Beginners Make
Learning React Before Understanding JavaScript
React becomes much easier when you understand modern JavaScript.
Do not skip the fundamentals.
Putting Everything in One Component
Large components quickly become difficult to maintain.
Break the interface into meaningful components as the application grows.
Calling APIs Directly Everywhere
Calling fetch directly inside a small component is fine for learning.
When many components communicate with the same API, moving HTTP operations into reusable services can keep the application cleaner.
Calling APIs Without Handling Failure
Network requests can fail.
Consider loading, success, empty, and error states.
Using useEffect Without Understanding It
Do not treat useEffect as a place for every piece of application logic.
Use effects when your component needs to synchronize with something outside React, such as an API request.
Trusting Client-Side Validation
React validation improves usability but cannot secure the backend.
Validate important data on the server.
Storing Secrets in Frontend Environment Variables
Anything included in the React application can ultimately be inspected by the browser.
Never store database credentials, private keys, passwords, or server secrets in frontend code.
Building Only Tutorial Examples
Tutorials help you learn individual concepts.
Building your own application teaches you how those concepts interact in a real project.
React vs ASP.NET Core: What Is the Difference?
React and ASP.NET Core are not alternatives to each other.
They normally handle different responsibilities.
| Technology | Primary Responsibility |
|---|---|
| React | Frontend UI |
| JavaScript / TypeScript | Frontend programming |
| C# | Backend programming |
| ASP.NET Core | API and backend |
| Entity Framework Core | Data access |
| SQL Server / PostgreSQL | Persistent data |
The overall architecture can be visualized as:
React
↓
User Interface
↓
HTTP / JSON
↓
ASP.NET Core + C#
↓
Business Logic
↓
Entity Framework Core
↓
DatabaseIs React a Good Choice for C# Developers?
React can be a useful frontend technology for C# developers who want to work across frontend and backend development.
Your C# experience can help with concepts such as:
Strong typing when using TypeScript
Interfaces
Application architecture
API contracts
Object-oriented design
However, frontend development introduces different concerns.
You still need to understand:
JavaScript
Browser behavior
HTML
CSS
Responsive design
Client-side state
HTTP communication
Browser storage
Frontend performance
React should therefore be learned as a frontend technology rather than simply another part of .NET.
Frequently Asked Questions
Can React work with C#?
Yes. React can communicate with a C# backend through HTTP APIs. ASP.NET Core is commonly used to build the backend API.
Do I need Node.js if my backend is C#?
Node.js is commonly used for the React development toolchain, package management, and local development even when your backend is written in C#.
Your ASP.NET Core backend remains a separate application.
Should a C# developer learn JavaScript before React?
Yes. Understanding modern JavaScript fundamentals will make React significantly easier to learn.
Should I use JavaScript or TypeScript with React?
Both are possible.
TypeScript can be particularly useful when stronger typing and explicit data contracts are valuable. C# developers may also find some TypeScript concepts familiar.
Can React work with SQL Server?
React should normally communicate with your backend API rather than connecting directly to SQL Server.
A common architecture is:
React
↓
ASP.NET Core
↓
Entity Framework Core
↓
SQL ServerCan I Use PostgreSQL Instead?
Yes. Your ASP.NET Core backend can use PostgreSQL through an appropriate database provider.
React does not need to know which database the backend uses.
Is React Only for Single-Page Applications?
No. React can be used with different application and rendering architectures. The right approach depends on requirements such as SEO, performance, hosting, interactivity, and application complexity.
What You Built and Learned
In this tutorial, you moved through the basic architecture of a React and C# full stack application.
You learned how to:
Create a React application
Build React components
Use JSX
Pass data through props
Manage state with
useStateLoad API data with
useEffectBuild an ASP.NET Core Web API
Return JSON from C#
Call the API from React
Move API logic into a service
Configure an API URL using Vite environment variables
Handle loading and errors
Create and delete data through HTTP requests
Use DTOs
Configure CORS
Connect ASP.NET Core to Entity Framework Core
Understand client-side and server-side validation
The complete architecture now looks like:
React Component
↓
React Service
↓
HTTP / JSON
↓
ASP.NET Core API
↓
DTO / Validation
↓
Business Logic
↓
Entity Framework Core
↓
DatabaseThat is the foundation of a real React and C# application.
What Should You Learn Next?
Once you are comfortable with this basic project, continue with features that solve real application problems.
Good next topics include:
Complete React CRUD
React Router
Form validation
ASP.NET Core authentication
Role-based authorization
Pagination
Search and filtering
Reusable React components
Centralized API communication
State management for larger applications
Testing
Production deployment
You do not need all of these concepts before building an application.
Learn them as your project begins to require them.
Final Thoughts
React and C# provide a practical combination for building modern full stack applications.
React handles the interactive frontend.
ASP.NET Core exposes APIs and processes backend requests.
C# implements application and business logic.
Entity Framework Core provides database access.
SQL Server or PostgreSQL can store persistent application data.
The complete flow can look like:
React
↓
ASP.NET Core Web API
↓
C#
↓
Entity Framework Core
↓
SQL Server / PostgreSQLIf you already know C#, do not begin your React journey by trying to learn every library in the React ecosystem.
Start with JavaScript and TypeScript fundamentals.
Then learn components, JSX, props, state, events, and basic hooks.
After that, connect React to a small ASP.NET Core API.
Build a product list.
Add a form.
Implement create, update, and delete operations.
Connect a database.
Then introduce validation, authentication, authorization, search, pagination, and other features as your project grows.
Most importantly, build while you learn.
Reading about useState introduces the concept. Using it in a product form helps you understand why it exists.
Reading about REST APIs explains the theory. Connecting React to your own ASP.NET Core API turns that theory into practical development experience.
A small React and C# CRUD project is enough to begin. You can gradually turn that project into a complete full stack application as your knowledge grows.
Comments 0