DEV Community

Osama Abu Motlaq
Osama Abu Motlaq

Posted on

I Learned React Before I Truly Understood JavaScript — Here's What Happened

If you're learning web development today, there's a good chance your journey looks something like this:

HTML → CSS → JavaScript → React → Next.js

At least, that's how it is supposed to go.

But what if you skip the part where you truly understand JavaScript?

That's exactly what I did.

I learned React before I had a solid understanding of JavaScript, and at first, it felt like I was making incredible progress.

I could build components.

I could use useState.

I could fetch data.

I could create forms.

I could build pages that looked like real applications.

Everything seemed fine.

Until it wasn't.

Eventually, I started encountering problems that React couldn't explain for me.

And that's when I realized something important:

I wasn't struggling with React. I was struggling with JavaScript.


React Made Me Feel Like I Was Progressing

When you start learning React, the progress can feel exciting.

You write:

function App() {
  return <h1>Hello World</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Then you learn components:

function UserCard({ user }) {
  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Then state:

const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

Then effects:

useEffect(() => {
  fetchUsers();
}, []);
Enter fullscreen mode Exit fullscreen mode

And suddenly, you're building applications.

That feels like real progress.

But there was a problem.

I could write the syntax.

I couldn't always explain what was happening underneath it.


The First Warning Sign: Array Methods

One of the first things that exposed this problem was something as simple as:

const activeUsers = users.filter(user => user.active);
Enter fullscreen mode Exit fullscreen mode

I knew that filter() returned an array.

But I didn't initially understand the function being passed to it.

What exactly was:

user => user.active
Enter fullscreen mode Exit fullscreen mode

Why does it run multiple times?

Where does user come from?

Why does filter() return a new array?

These aren't React questions.

They're JavaScript questions.

And React uses these concepts everywhere.


Then Came Destructuring

React code is full of destructuring.

For example:

const { name, email } = user;
Enter fullscreen mode Exit fullscreen mode

Or:

const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

At first, I treated this as React syntax.

It isn't.

It's JavaScript.

The second example is simply array destructuring applied to the value returned by useState().

Once I understood destructuring properly, React code became much easier to read.


Then I Met the Spread Operator

Another example:

const updatedUser = {
  ...user,
  name: "Osama"
};
Enter fullscreen mode Exit fullscreen mode

I knew that this was commonly used in React.

But knowing how to use it and understanding what it actually does are two different things.

The spread syntax is JavaScript.

React doesn't own it.

React simply makes heavy use of JavaScript features like this.

The same applies to:

map()
filter()
reduce()
find()
some()
every()
Enter fullscreen mode Exit fullscreen mode

If your JavaScript foundation is weak, React code can quickly become a collection of syntax that you memorize instead of concepts that you understand.


useState Wasn't the Real Problem

At some point, I started asking:

"Why does React need state?"

I knew how to write:

const [count, setCount] = useState(0);
Enter fullscreen mode Exit fullscreen mode

But understanding React state requires a deeper understanding of JavaScript concepts.

Variables.

References.

Objects.

Functions.

Closures.

Immutability.

Execution.

Re-rendering.

For example:

const user = {
  name: "Osama"
};

user.name = "Ali";
Enter fullscreen mode Exit fullscreen mode

This changes the existing object.

But in React, you will often work with state like:

setUser({
  ...user,
  name: "Ali"
});
Enter fullscreen mode Exit fullscreen mode

Why?

Because understanding object references and immutable updates becomes important when working with React state.

Without understanding JavaScript, React's rules can feel arbitrary.


Then this Appeared

JavaScript's this was another wake-up call.

I had seen code like:

const user = {
  name: "Osama",

  sayHello() {
    console.log(this.name);
  }
};
Enter fullscreen mode Exit fullscreen mode

Then I encountered arrow functions:

const user = {
  name: "Osama",

  sayHello: () => {
    console.log(this.name);
  }
};
Enter fullscreen mode Exit fullscreen mode

Why do these behave differently?

Why does this depend on how a function is called?

Why don't arrow functions have their own this?

These aren't React concepts.

But if you don't understand them, JavaScript can feel unpredictable.

And when JavaScript feels unpredictable, React becomes even more confusing.


Closures Changed Everything

Closures were probably one of the most important concepts I eventually had to understand.

Consider:

function createCounter() {
  let count = 0;

  return function () {
    count++;
    return count;
  };
}
Enter fullscreen mode Exit fullscreen mode

The returned function can still access count.

Why?

Because of closures.

And closures are not some obscure JavaScript feature that only matters in interviews.

They are fundamental to understanding how functions retain access to variables from their surrounding scope.

Once you understand closures, many concepts in modern JavaScript start making more sense.

Including patterns you encounter when working with React.


Async JavaScript Was Another Story

Then came API requests.

I started with something like:

fetch("/api/users");
Enter fullscreen mode Exit fullscreen mode

Then:

fetch("/api/users")
  .then(response => response.json())
  .then(users => {
    console.log(users);
  });
Enter fullscreen mode Exit fullscreen mode

Then:

async function getUsers() {
  const response = await fetch("/api/users");
  const users = await response.json();

  return users;
}
Enter fullscreen mode Exit fullscreen mode

I knew how to write the code.

But understanding asynchronous JavaScript required much more than memorizing async and await.

I had to understand:

  • Promises
  • Callbacks
  • The Event Loop
  • Microtasks
  • Asynchronous execution
  • Error handling

And suddenly, something that looked like a React problem turned out to be a JavaScript problem again.


The Biggest Mistake Was Learning Syntax Instead of Concepts

Looking back, I wasn't really learning React.

I was learning how to make React code work.

There's a big difference.

Learning syntax looks like:

"How do I write useEffect?"

Learning concepts looks like:

"What problem is useEffect solving, and what does this code actually do?"

Learning syntax:

"How do I update state?"

Learning concepts:

"Why does React care about state updates and references?"

Learning syntax:

"How do I fetch data?"

Learning concepts:

"How does asynchronous JavaScript work, and what happens while I'm waiting for the response?"

The second approach takes longer.

But it creates a much stronger developer.


React Started Making More Sense After I Went Back

Eventually, I made what felt like a step backward.

I went back to JavaScript.

Not because React was bad.

Not because I wanted to abandon modern development.

I went back because I needed the foundation.

I started focusing on:

Variables
Data Types
Functions
Arrays
Objects
Scope
Closures
this
Prototypes
Destructuring
Spread Syntax
Array Methods
Promises
async/await
Event Loop
Modules
DOM
Events
Error Handling
Enter fullscreen mode Exit fullscreen mode

And something interesting happened.

I didn't feel like I was starting over.

I was finally connecting the pieces.


React Became a Layer Instead of a Mystery

Before that, React sometimes felt like a collection of special rules.

After understanding JavaScript better, I started seeing React differently.

React became another layer on top of concepts I already understood.

For example:

users.map(user => (
  <UserCard key={user.id} user={user} />
))
Enter fullscreen mode Exit fullscreen mode

Before:

"That's React syntax."

After:

"map() is JavaScript. The arrow function is JavaScript. The object being passed is JavaScript. React is using these concepts to describe UI."

That distinction is extremely important.


The Framework Shouldn't Be the Foundation

A framework should sit on top of your fundamentals.

Not replace them.

Think about it like this:

                Next.js
                   ↓
                 React
                   ↓
              JavaScript
                   ↓
          Programming Fundamentals
Enter fullscreen mode Exit fullscreen mode

If the bottom layer is weak, everything above it becomes harder.

You can still build things.

You can still follow tutorials.

You can still copy patterns from documentation.

But debugging becomes much harder.

And sooner or later, you'll encounter a problem that the tutorial didn't cover.

That's when fundamentals matter.


Does This Mean You Should Master JavaScript Before React?

Not necessarily.

I don't think you need to spend years learning JavaScript before touching React.

You can learn both together.

The important part is not letting React replace your JavaScript learning.

A healthy learning path could look like:

HTML + CSS
      ↓
JavaScript Fundamentals
      ↓
Small Vanilla JS Projects
      ↓
React
      ↓
Advanced JavaScript
      ↓
Next.js / Node.js
      ↓
Full Stack Development
Enter fullscreen mode Exit fullscreen mode

You don't have to know everything before moving forward.

But whenever React exposes a JavaScript concept you don't understand, stop and learn that concept.

That's much better than memorizing the React-specific solution.


Build Something Without React

One of the best things I did was build projects using Vanilla JavaScript.

Not because Vanilla JavaScript is better than React.

But because it forced me to understand what was happening.

For example, building a Todo application without React makes you think about:

  • DOM manipulation
  • Events
  • State
  • Data structures
  • Array methods
  • Forms
  • Local Storage
  • Rendering
  • Updating the UI

Then when you build the same kind of application with React, you start appreciating what React is actually solving.

You don't just use the abstraction.

You understand why the abstraction is useful.


The Real Lesson

The biggest lesson wasn't:

"Don't learn React early."

The lesson was:

"Don't let learning React prevent you from learning JavaScript."

React is an incredibly powerful tool.

But tools change.

Frameworks change.

Libraries become unpopular.

New technologies appear.

The fundamentals remain.

If tomorrow you move from React to another framework, your JavaScript knowledge comes with you.

That's your transferable skill.


If You're Learning React Right Now

Don't panic if you're already learning React.

You don't need to throw away everything you've learned.

Instead, whenever you encounter something you don't understand, ask:

"Is this actually a React concept, or is it JavaScript?"

For example:

map()?

JavaScript.

Destructuring?

JavaScript.

Spread syntax?

JavaScript.

Closures?

JavaScript.

Promises?

JavaScript.

async/await?

JavaScript.

Modules?

JavaScript.

Objects and references?

JavaScript.

Once you start making this distinction, your learning becomes much more structured.


Conclusion

Learning React before deeply understanding JavaScript wasn't a complete mistake.

It actually taught me something valuable.

It showed me exactly why fundamentals matter.

React can help you build applications faster.

But JavaScript helps you understand what your application is actually doing.

You don't have to choose between modern frameworks and strong fundamentals.

Learn both.

Use React.

Build with Next.js.

Work with Node.js.

Explore the ecosystem.

But whenever you feel that a framework is doing something "magical," go one level deeper.

Ask what's happening underneath.

Because eventually, you'll discover that much of the "magic" isn't magic at all.

It's JavaScript.

And the better you understand JavaScript, the less mysterious React becomes.

Don't learn React to avoid JavaScript. Learn JavaScript so you can truly understand React.

Top comments (0)