Posted Sep 29, 2026 · 5 min read · 1 view
React Basics for Beginners: Components, State, and Fetching Data
React is one of the most popular ways to build user interfaces, and it is a common requirement in job listings. The concepts can feel overwhelming at first, but you only need a few core ideas to build real things.
In this tutorial you will set up a React project with Vite, learn components, props, state, and effects, and build a small app that fetches and filters data from an API.
What you need
- Node.js 18 or newer installed
- Basic knowledge of HTML, CSS, and modern JavaScript (arrow functions, destructuring,
map) - A code editor such as VS Code
Step 1: Create a project with Vite
Vite is a fast build tool and the standard way to start a new React project today:
npm create vite@latest devs-list -- --template react
cd devs-list
npm install
npm run dev
Open the local URL that appears in your terminal. You will see the starter page. The important files are:
index.html: the single HTML pagesrc/main.jsx: the entry point that mounts your appsrc/App.jsx: your root component
Open src/App.jsx, delete everything inside, and replace it with:
export default function App() {
return <h1>Hello, BD Devs</h1>;
}
The page updates instantly, without a manual refresh.
Step 2: Understand components and JSX
A React component is just a function that returns UI. The syntax that looks like HTML is called JSX. Create src/Greeting.jsx:
export default function Greeting() {
return <p>Welcome to the community!</p>;
}
Use it inside App.jsx:
import Greeting from './Greeting';
export default function App() {
return (
<div>
<h1>Hello, BD Devs</h1>
<Greeting />
</div>
);
}
A few JSX rules to remember:
- Component names must start with a capital letter
- A component must return a single root element (wrap siblings in a
divor a fragment<>...</>) - Use
classNameinstead ofclass - Put JavaScript expressions inside curly braces:
{name}
Step 3: Pass data with props
Props let a parent component send data to a child. Update Greeting.jsx:
export default function Greeting({ name, city }) {
return <p>Hi {name} from {city}!</p>;
}
Then use it with different values:
<Greeting name="Rahim" city="Dhaka" />
<Greeting name="Karim" city="Chattogram" />
Props flow in one direction, from parent to child, and a child should never modify them. This one way flow makes React apps easier to understand.
Step 4: Add state with useState
Props are inputs. State is data that a component owns and that changes over time. When state changes, React re-renders the component.
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}
useState(0) returns the current value and a function to update it. Two important rules:
- Never change state directly. Write
setCount(count + 1), notcount = count + 1. - When the new value depends on the old one, use the updater form:
setCount(prev => prev + 1).
For objects and arrays, create a new copy instead of mutating:
setUsers([...users, newUser]); // add
setUsers(users.filter(u => u.id !== idToRemove)); // remove
Step 5: Render lists and handle input
Let us build a searchable list. Create src/DevList.jsx:
import { useState } from 'react';
const devs = [
{ id: 1, name: 'Rahim', skill: 'Laravel' },
{ id: 2, name: 'Karim', skill: 'React' },
{ id: 3, name: 'Nadia', skill: 'Python' },
];
export default function DevList() {
const [query, setQuery] = useState('');
const filtered = devs.filter(d =>
d.skill.toLowerCase().includes(query.toLowerCase())
);
return (
<div>
<input
value={query}
onChange={e => setQuery(e.target.value)}
placeholder="Search by skill"
/>
<ul>
{filtered.map(dev => (
<li key={dev.id}>{dev.name} - {dev.skill}</li>
))}
</ul>
</div>
);
}
Notice two things. The input is a controlled component, meaning its value comes from state. And every list item needs a stable, unique key, such as a database ID. Avoid using the array index as a key when the list can change order.
Step 6: Fetch data with useEffect
Real apps load data from APIs. Side effects like fetching belong in useEffect:
import { useState, useEffect } from 'react';
export default function Users() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
fetch('https://jsonplaceholder.typicode.com/users', {
signal: controller.signal,
})
.then(res => {
if (!res.ok) throw new Error('Request failed');
return res.json();
})
.then(data => setUsers(data))
.catch(err => {
if (err.name !== 'AbortError') setError(err.message);
})
.finally(() => setLoading(false));
return () => controller.abort();
}, []);
if (loading) return <p>Loading...</p>;
if (error) return <p>Something went wrong: {error}</p>;
return (
<ul>
{users.map(u => <li key={u.id}>{u.name}</li>)}
</ul>
);
}
Key points:
- The empty dependency array
[]means the effect runs once after the first render - Always handle loading and error states, not only the happy path
- The cleanup function cancels the request if the component unmounts, which prevents state updates on components that no longer exist
In development, React Strict Mode runs effects twice to help you spot bugs. That is normal and does not happen in production.
Common beginner mistakes
- Mutating state directly, which causes the UI not to update
- Missing keys in lists, which triggers warnings and odd behavior
- Missing dependencies in
useEffect, which causes stale data. If your effect uses a value, it usually belongs in the dependency array - Putting everything in one giant component. Split UI into small, focused components
- Fetching data on every render by forgetting the dependency array
Where to go next
Once these basics feel comfortable, learn these in order:
useRefanduseContextfor shared values- Custom hooks to reuse logic
- React Router for multiple pages
- A data fetching library such as TanStack Query
- TypeScript with React
Final thoughts
React looks large, but almost everything builds on the same idea: your UI is a function of your data. Change the state, and React updates the screen. Practice by building small projects, like a todo list, a weather app, or a job board, and the concepts will stick faster than any tutorial.
What was the hardest React concept for you to grasp? Tell us in the comments.
Discussion (0)