Getting React running on your machine
You need Node.js installed first. If you don't have it, download the LTS version from nodejs.org. I'm not going to explain why you need it. It just works that way. The latest stable release at the time of writing is 20.x, and it pairs fine with everything in this guide. Once Node is in place, open a terminal and run npx create-react-app my-first-app. That's the official scaffolding tool from the Meta team. It sets up a complete project structure with Webpack, Babel, and everything else a beginner would struggle to configure manually. The command downloads roughly 150 packages and takes about 2-3 minutes on a decent connection. On a slow one, maybe 8 minutes. Don't try to speed it up by cancelling and restarting. It'll just break.
React Setup Guide For Beginners
After the installation finishes, navigate into the directory with cd my-first-app and then run npx create-react-app my-first-app --template typescript if you want TypeScript from the start. I say this because I've seen too many people build the plain JavaScript version first, then try to migrate later. It's not hard, but it's unnecessary friction. TypeScript catches type errors before they reach the browser, which saves debugging time you won't get back. Start the dev server with npm start. This launches a local development server on port 3000. You'll see the default React welcome page in your browser. Open the project folder in VS Code or whatever editor you use. Your main entry point is src/App.js or src/App.tsx if you used the TypeScript template. That's where you'll write your components. Here's something most guides don't mention: the dev server uses Hot Module Replacement by default. When you save a file, only the changed component re-renders in the browser. The rest of your app state stays intact. This means you can fix a bug in a deeply nested component without losing your form inputs or navigation state on the page. It sounds like a minor detail. It isn't. I spent two weeks debugging a state reset issue before I realized HMR was actually saving me from having to reproduce a complex scenario manually each time.
Now let's talk about the project structure. Inside your src folder you'll find App.js, index.js, logo.svg, and reportWebVitals.js. The entry point is index.js. It imports React, ReactDOM, and the App component, then mounts it to the DOM using document.getElementById('root'). This never changes. Don't touch it unless you know what you're doing. The App.js file is where you'll spend most of your time. It starts with a functional component that returns JSX. JSX looks like HTML but it's actually JavaScript syntax extension. The browser can't read it natively, which is why Babel compiles it during development. If you're wondering why your code won't run when you open the file directly in a browser without the dev server, that's the reason. I encountered a specific issue once that took me about four hours to resolve. I was building a small dashboard and noticed that after adding a few custom hooks, the dev server would freeze every time I saved a file. No error message, just a completely hung process. The solution was that one of my dependencies had a peer dependency conflict with React 18's concurrent features. I pinned the problematic package to an older version in package.json using the caret notation with an exact version constraint, then ran npm install again. The server stabilized immediately. This doesn't happen often, but when it does, the error messages are typically unhelpful.
Get the Full Details

When you're ready to deploy, run npm run build. This compiles your code into a static assets folder called build. Everything in there is production-ready. The build minifies JavaScript, optimizes images, and hashes filenames for caching. A typical build of a small app comes out to around 200-400 KB minified. Not massive, but not tiny either. If your build output is over 1 MB, something is wrong. Check for unused dependencies, large image files, or libraries you imported but never used. One counter-intuitive thing about React that beginners consistently miss: useState does not update state immediately. When you call a setState function inside an event handler, the variable you're reading still holds the old value for the rest of that function's execution. This trips people up constantly. The fix is to either use the functional updater form or read from the new value after the render cycle completes. I write setCount(prev => prev + 1) instead of setCount(count + 1) as a habit. It prevents bugs when multiple state updates happen in the same event handler. Another nuance: React 18 introduced automatic batching. In React 17, state updates inside promises and setTimeout were not batched together. Each update triggered a separate re-render. In React 18, all updates inside any async callback are batched automatically. This is usually better for performance but can be surprising if you wrote code in React 17 expecting immediate synchronous re-renders. If you ever need the old behavior, React provides unstable_batchedUpdates from react-dom, but almost no one actually needs it.
Environment variables work differently than you might expect. Create a file called .env in your project root. Prefix any variable you want accessible in the browser with REACT_APP_. For example, REACT_APP_API_URL=https://api.example.com. Then reference it in your code as process.env.REACT_APP_API_URL. Variables without the REACT_APP_ prefix exist but are not exposed to the browser bundle. This is a security measure baked into the tooling. There are real limitations to the Create React App approach that you should know about. It hasn't received a major update in years. The team behind it is moving toward alternatives like Vite and Next.js. CRA uses Webpack under the hood, which means longer build times as your project grows. A medium-sized app with CRA can take 30-60 seconds to do a full production build. Vite does the same build in under 5 seconds because it uses native ES modules in development instead of bundling everything upfront. If you're starting a new project today and aren't locked into CRA for some reason, Vite is the faster option. Testing is another area where CRA falls short. The included testing library setup is basic. It works for unit tests but doesn't scale well to integration or end-to-end testing. Most teams add their own testing infrastructure after a few months. Jest is bundled in by default, which is fine for component tests. For anything beyond that, you'll likely add Cypress or Playwright separately.
If you want to learn React properly, don't skip the fundamentals. Learn how components render, how props flow down, and how effects work before reaching for state management libraries. Zustand, Redux, and MobX are tools that solve problems you don't have yet. I've seen junior developers add Redux to projects with three components and six state variables. It adds complexity without solving anything. React's built-in useState and useReducer handle the vast majority of use cases. Here's a quick checklist for getting started: Install Node.js LTS version. Run npx create-react-app with the TypeScript template if you want type safety. Open the project in your editor. Edit App.js to create your first component. Run npm start to see it in the browser. Run npm run build before deploying. Keep your dependencies updated but test breaking changes in a separate branch first. The semver system exists for a reason and most breaking changes will be caught during the upgrade process if you read the changelog.

That's it. The tooling handles the complexity so you can focus on learning the framework.