DEV Community

Cover image for From JavaScript to React: Building Real Projects with The Odin Project
John Walter Munene Njeru
John Walter Munene Njeru

Posted on

From JavaScript to React: Building Real Projects with The Odin Project

WeCoded 2026: Echoes of Experience šŸ’œ

Originally published at Medium.

From JavaScript to React, I share how building real projects with The Odin Project helped me grow from learner to confident React developer.

I’ve recently finished The React Course at The Odin Project and I wanted to step back, reflect on my experience and progress in web development. When I started The Odin project, I had prior basic programming skills from my Electrical and Electronics Engineering classes with little to show of it for I couldn’t build anything working let alone the thoughts of production. Now that I have been hacking my way into programming through The Odin Project, I wanted to inform anyone about what they can expect and how my journey has been uniquely rewarding.

When I first finished the JavaScript course, I wrote a title named ā€œFrom Beginner to Builder: My Journey Learning JavaScript with The Odin Projectā€, which has brought me many visitors and a small community here on Medium. I’m thankful to everyone who has been following me since, so this will be a follow up of my progress since then. While this article won’t cover all of my explicit challenges and ā€œahaā€ moments, it should help you have a holistic overview of what a structured progression from writing JavaScript to React feels like. Let’s dive in!

Looking Back: From JavaScript to React

When I started to learn programming on a serious level, I only wanted to get how things work, and not feel left out in conversation about software development, although writing in the space was my main goal. I had a year’s toil understanding how JavaScript works under the hood, as in the syntax and the browser operation model (well explained if you have read about the journey in the linked article).

I had built a few applications using Vanilla JavaScript and was starting to feel proud of my progress as a programmer. Even though I hadn’t built any fancy or modern websites, I had a comprehensive suite under my belt. In the JavaScript course, I had built a few projects such as a Weather app, a battleship game, and even played around with some basic data structures and algorithms. The Battleship game was the ultimate project and with it, I had tinkered with Test Driven Development but I had no idea on how to test my UI, apart form running it myself with lost of hassle on the context of debugging, console log statements being the savior.

On finishing the Project I wanted to continue this learning so I didn’t halt at that checkpoint. Rather I extended my efforts and started learning ReactJS, the most popular library for building user interfaces to take my frontend skills to a whole new level.

Why React Felt Different

At first, React felt like I was fighting programming. This isn’t because of learning a new syntax for writing HTML and JavaScript in a single file is hard to grasp, but because it’s a complete shift into a new programming paradigm. My adventure began with an introduction to React, setting up a React environment, writing JSX, rendering techniques, the concept of keys in React and passing data between components. I the proceeded to state in programming, and then did a deep dive into it on the scope of managing it and adding interactivity.

The lessons on Odin give a good introduction on all of the above topics. Instead of just reading through the lessons, I went ahead to read through all of the linked resources into the React documentation. When I got to the CV application project, the first one in the curriculum, I had spent so much time reading all about state management, and my mentals on writing JSX and the preceding topics had sort of faded into the winds and so I redid the intro lessons once more, this time with a clean focus on the basics as I had done a deep dive. This was meant to bring step back and bring things into perspective as I was well equipped with what is down the state management rabbit hole.

To mention of a few things about state, your application could take any shape, and based on how you want the product to behave, and thus interactions are the ones dictating what shape your state takes. Note that this doesn’t come automatically as you’ll need to have spent some time with React to internalize the building model, and you’ll also need to understand the least changing data in your application as it goes without saying, it’s what gets tucked into state. Since, I struggled a lot in my first days, I kept close kin, the title ā€œThinking in Reactā€ which is a detailed guide on how to solve problems in React. This was an article I read many times whenever I was stuck or needed to touch an application I was writing. In this case it was my CV application.

Thinking in Components: The Shift That Changed Everything

After finishing my CV application, I went further to delve deeply into dealing with side effects in React, a way to synchronize your application (DOM) with external activities or procedures. Similar to the state bits, this was another interestingly deep rabbit hole with much to learn that in the end the documentation cautions on when to use state to handle interactions, the appropriate way to use effects, and a note of side effect events, and when to opt for either based on your needs. Things were a bit confusing but on taking note that they side effects are a way of React applications to interact with the outside world I was good to go. In fact, the best lesson learned on this was that I should explicitly separate application specific events in terms of user interaction in contrast with system specific events.

I wrapped up my effects lessons with a nice memory card project which too, in my development was influenced so much by the Thinking in React guidelines. It was not until I a completion of this project that I felt the state and effects click. By the end of this project, I had developed a good intuition on what a good effect looked like, and while at it I had made the use of the Giphy API SDKs, and had my state well structured. Being my second project and seeing it come to life filled me with much joy looking back that when I started programming, I really struggled with writing loops.

When I had a working model of the memory card game, I refactored my methods to move them from child elements to a parent to reduce the recreation for methods on every item. While this isn’t a worry for small applications, knowing when something should be defined in the parent rather than the child was something important that I learned. This is a concept that goes hand in hand with the worry about where state should live in your application. I had my friend Sam check my solutions for this project and he signaled that I was progressing relatively well. In the light of looking at lessons learned, this project helped me learn about managing state while working on a real game project. My first CV project was ugly, but my memory card game was better, both in terms of code and final output. Nevertheless, I had working applications.

Completing this project and seeing work came with a rejuvenation and the urge to proceed forward to learn more about React. Next-in-line was class-based components. While these are relatively used in older code bases, they helped give a different understanding of side effects and how to reason about them. This section was also about explicit handling of effects using classes and through a slightly different syntax even though the end results are the same. From the development learning point of view, these were meant to equip on handling older code bases suppose you met one along the programming journey.

So far, I was getting deep into the React ecosystem but I hadn’t felt like I was doing much. I had a simple flow of walkthrough through type checking with prototypes for better development, and to have an explicit alert when a function didn’t use the correct props. All this changed when I started using the React router and there were suddenly some extra things to pick on like defining routes, using outlets, exporting routes in their files, and organizing the code around routers.

While these weren’t really hard, they braced me to get further and I was now working on how to test React applications. Well, here came an interesting challenge where testing in React is slightly different from writing Jest logic tests yet the mental model around the testing of the syntax remained the same. Snapshot tests were now a new way to test modern codebases but the though of getting false positives and negatives had me steering away towards writing actual tests that asserted what I aimed out of the application.

The Odin Project had shallow details in regards to testing, and so I decided to supplement my knowledge on testing by looking at the React Testing lessons from Full stack Open. I finally got a solid idea and was now ready to work on my final React project, a working shopping cart, a project that challenged me the most but also stitched everything into context around how React works. I also ended up looking at styling React application methods and opted to use CSS modules on moving forward. I didn’t want to use Tailwind as Odin warns on early adoption of frameworks without solid and comprehensive knowledge of CSS. Other options like CSS-IN-JS looked appealing but I’m a lover of clean syntax, and so modules were my final choice, a step better than vanilla itself, with little or no difference from it, only by scoping as the new rule.

Shopping Cart: The Project That Stretched Me the Most

I had now been somehow deep into React and this project came at an appropriate time that I had to step back and put everything I had learned into practice. Because The Odin Project has a very good encouragement on taking final projects on a course seriously, I resolved to work on something worthwhile in terms of what my code and output would look like. Odin has well described steps or approaching a project and this was no different. The only exception was, I have to architecture my whole application from scratch making all the design decisions.

This time, I did not need to look at the Thinking in React as I had acquired my own ways of approaching applications. While the docs will talk about the top to bottom and bottom to top ways of building react applications, I have come to conclude that the best way is a dual mode where you think of the top as pages, but then fall back to the bottom and build gradually to the top. There’s now straight separation of the two. Instead, it’s a back and forth.

As usual, I adopted my application into three static pages, the home page, the shop page and the cart pages. I started by populating my home page, ensuring my shop page handles the errors, and loading states, correctly, move forward to the population with cards and thus wrote some effects, and then I proceeded to the cart page. Worthy of note is that the development of these pages came after writing my navigation bar which I had to refactor when writing shop and cart pages to include some extra information while at them.

An important thing to mention is that while working on these pages, you are also forced to think about the minimalistic changing data in the application (which is the state) and where to put it. I was forced to think about using outlets to render my home and carts but straight out realized that it’d be a bad practice if I’m handling conditional rendering in routes in the absence of things like authentication. I opted to define my state in the App.jsx component as well as the routes, passing state down and it’s updaters to the correct components. That way my application’s pages could be tested in isolation, and if in any case, when each page updated it’s parent state correctly, the other pages wouldn’t have to worry about them only consuming the updated state.

While working on the specifics of my shop and cart pages, I tried implementing methods both on children and parent components so that I could have a look at how each programming pattern would have an effect on how I’d approach my tests. On getting my tests to pass for all my components, and testing the UI with a skeleton on running build, I was sure that minimally my application was working and all I needed was to style it. Using CSS modules was really easy to style my app as there were no worries about conflicting rules even if there was a need to have clear layout defined at the component level. I this app I leverage the composition programming pattern, which I wasn’t aware of, yet it still adapted naturally to my coding style. This project really frustrated me.

Debugging, Deployment, and Testing Frustrations

Even if no one says it out, I found it tough to debug tests and to get them pass. Note that unlikt in jest where we assert logic, here we are actually testing the behavior of the UI by waiting for actions to be called and then testing the DOM changes for expectations. It’s not that testing is difficult, but there’s a learning curve to have your tests passing correctly. Again, some lessons aren’t taught during tutorials but can only be felt on hands on experience. I’ll give an example for context.

If you opt to write tests using query selectors for classes, it’s easy to get them working real quick. The only problem is that when you switch to using CSS modules, the class names are hashed and now unavailable in the tests. This means that some time had to be spent refactoring my project to pick elements using the right queries and some weird quirks had to be resolved. For example, the testing documentation doesn’t outrightly state that async operations using ā€˜forEach’ are a bit tricky and do not await callbacks forcing tests to fail. Instead, I had to use the ā€˜for…of’ or the regular ā€˜for’, or while loops for sequential operations. Again, if you have utility functions in your components, they’ll need to be called inside the tests to ensure congruence in results.

Another thing that I couldn’t fix was the fact that when I installed my router, the linter rules were now changed the propTypes stopped working. When I was writing tests for my router, to check that navigation clicks worked, I was forced to install a slightly different package and work with it — as in react-router for the app, and react-router-dom for testing with the React Testing Library. Again it is also worthy of note that testing the application had nearly an equal amount of code to that of the application itself.

Getting tests to pass was one thing, and now that my application was styled and working, the final bit was deployment. I chose to work with Vercel but had lots of trouble for some inconsistent naming of exports and imports. In this case, React is forgiving that when you run ā€œnpm run devā€ it works well on local host but won’t build on pulling my repo to Vercel. To fix this, I read the Vercel docs that guided on making local builds (like with webpack) run is the right step to getting the application run and deploy of vercel. I struggled my way out by cleaning up the application naming, using some simple bash scripts to automate the figuring out of which parts differ. When my build worked, I run my tests once more before using Vercel deployment commands locally. In this case the command line was really a close tool to work with. I’ve finally deployed my shopping cart (no media queries as of this writing), and here is the source code. Here’s the look of the cart page.

What The Odin Project Gets Right About Learning React

Just like I said in my other article about how The Odin Project teaching how to program by equipping you with the necessary skills to tackle any problem, this has still been the format. I’m in love with the teaching method where you take on some lessons before projects and that they are well structured in incrementally increase the load. The only truth I have realized if you read through all the lessons and grasp all what is required no project will be impossible. The projects aren’t simple, but they are doable based on preceding knowledge.

If you’re still wondering if it’s the best way to learn React, then you’re at the right place. One, the learning is structured and self-paced so you don’t have any pressure, and you move at your own pace on the expectations that you’re self-aware of your learning goals. Second, The Odin Project teaches through following many unique tutorials, and finally combining them with a project so you can build with confidence. Nothing beats project exposure. Learning through tutorials feels productive as you are making steps, but working on a project tests all the learned concepts in a single sling that you have to make use of everything to create a working web application.

The final thing to keep in mind is that learning by documentation feels slow and deep but the benefits are crystal clear. The docs give in-depth guides around a topic and text is easily updated with the rolling out of new features, both in React and the JavaScript or Browser updates which are not easy to adapt into content if you’re on videos. This is not trashing videos as a way to learn but I have found videos more resourceful when taken to explore different examples and as a supplement to documentation. Would I still recommend Odin, a triple yes as usual. Give it a shot!

Lessons I Didn’t Expect to Learn

There are many lessons that I’ve picked up along the way like how programming is easy with React and how it gets you building projects faster and in an easy way. So far, I’d recommend learning React topics in this order: JSX, Rendering Techniques, Keys in React, Passing Data Between Components, state, side effects, class-based components, component life cycle methods, testing (spend some extra time on this one), react router, type checking, fetching data, and styling applications. With a good grasp of these, you can build nearly any project provided that you use each tool for what it’s meant for.

Again, React does a good job at testing your fundamentals of JavaScript. Had my understanding of JavaScript been shallow, I wouldn’t have made it through this course. I have also learned that getting a working project teaches more than any independent lesson in isolation. Where each tutorial is meant to hold your hand through solving a particular problem, a project forces you think about the whole application in terms of expected output, how you make your architecture suite the application and translating your thoughts into working code. Many people will tell you once you get the sytax you’ll be good to go but learning how to solve problems is equally important. And this, if I must stress on harder, can’t be taught by following blindly following tutorials, but rather by intentional learning.

In addition, a lot of resilience is needed to get through this course. I have also realized that I do not need lots of hand holding and I’m naturally knowing when to reach out for specific tools, and where to find them. My own code solutions for React were really ugly but they have also really improved by the third project and I can’t really wait to know what lies ahead of where I am at. A lot of research is also needed to make working solutions as there’s nearly a solution for every specific problem in JavaScript, but knowing how to stitch them to work together and correctly is the real labor around programming.

What’s Next in My Developer Journey

I’m writing this as I close the first phase of my development journey now that I can say at least the frontend is covered. Looking forward, I’m at a point where I can start reading about design patterns and architecture, and I’m now going to be confidently matching into backend development. I will only proceed further by learning better programming patterns on frontend development as I simultaneously hack my way into the backend.

My take is that it has not been easy but it has been a suitable and challenging journey with lots of learning and humility needed. When I shared my final project to a working full-stack developer for review, I’ve received lots of positive criticism that will force me to go back to my project and to make improvements. I can’t help but admit that following the comments I received, I have moved from wondering how to make it work to how best should this look and work alike. This means that we are talking of designs in the UI/UX and how they can be improved unlike how do I center a div or write my first program.

Not only has the journey been a little faster when I compare it to what it took to complete the JavaScript course. By the numbers React has taken me six months to have it flowing while JavaScript took me a whole year. This is by far the biggest indicator that I’m learning and my pace is taking quicker revolutions in terms of speed. I’m still on the path to becoming a full-stack developer and so I will be proceeding to Databases, and finally the Node.js course. I had started learning API documentation and I pause this to embark on it once I build my first API so this is something I’m hopeful I can do in the coming months.

That said, I happy to progress and call myself a frontend developer with hope that in due time, I will be a full stack developer writing about JavaScript while getting paid to learn in a role or at least building my own projects that actually translate to a better bank account. Till, then, I’ll keep Reacting to it in JavaScript, and hope to Node it down as well. If you’d like to chat me more or even offer an opportunity, I’m available on all social platforms.

Please send me an email, shoot me a DM on X (formerly Twitter), or even review my code on GitHub. Better still, if you’d like to collaborate, my LinkedIn is open to new networks. Cheers and happy coding! See you in the next article.

Originally published at Medium.

Top comments (0)