Learn any new Frontend framework

Learn any new Frontend framework

Sharing approach and keynotes from learning new frontend frameworks emerging in the web and mobile world. With example of React client app.

Why learn?

As a developer, we know, that the technological environment changes rapidly. Keeping up with new concepts, frameworks and tools is crucial for being a viable player in the market or even internally within your company.

Recently I was reshuffled to a project doing frontend exclusively in React. I did work with React before in another company, but this was long before hooks were introduced. Certainly, a lot has changed since that, and a leap from Angular to the React world, can be intimidating. I have experience in other frameworks starting with good old jQuery, through AngularJS, Angular and Vue3. I even did a fair amount of WPF a long time ago. What is most important I was also given time to learn. So I did.

Let me tell you how.

“Tell me and I forget, teach me and I may remember, involve me and I learn.”
Benjamin Franklin

The quote nicely wraps up, what I want to tell you. But how do you approach this in the development world?

I will describe step by step the kind of learning framework I figured out during the years of working in different commercial and private projects. If you feel like it, follow it, or maybe pick the parts that speak to you the most.

Disclaimer: This article is written from the JS web UI frontend perspective. I assume you have already some experience in any of the existing frameworks or at least knowledge of HTML and JS. But even if you don't write in JS or you just start with Frontend, you will find some value in the words below.

Grab the concept

Start here to get a very basic view of what it is you will learn.

Read a little about the framework.

  • How it works?

  • How is it different than others?

  • What are the core concepts behind it?

For React I learned that it is basically a functional representation of UI written in jsx (or tsx for typescript) format. Even though components have a state, they are immutable: every state change requires rerendering of the component.

That alone is enough to have a lot of questions about specific cases it can be used with, and how it behaves in comparison to other frameworks you might already know.

But don't worry about it now, we will dispute a lot of these concerns whilst doing the implementation.

Make it fun or useful

Or ideally both.

Even a test project does not need to be dull. Come up with a project that is fun or brings real value.

  1. The topic should be interesting for you. Writing another to-do app might be boring. It is much better to work towards something you (Or someone else) might actually use.

  2. Do not bring a big topic to the table, you will not make it work in time, or the quality will suffer. If you intend to do a big project, try on one small functionality first.

Given these two rules, you will feel engaged in your project, and learning will come naturally along the way.

Keep it simple

At first.

A simple page with some list and form that allows for interaction with the backend will still be a lot of work if to be done properly.

  1. Do not care about the backend. Either use some existing free API to fetch data or just write some .json files and import them directly to code.

    💡
    Things get trickier for posting messages back to API. If you don't have backend API ready then use some tools like Postman, json-server, amock.io or simply do an in-memory service faking its behavior.
  2. Find out how they do it now: code structure, conventions, configuration etc. to start coding quickly and do not think too much about setup details. Use the tooling for this if applicable.

    • For React: create-react-app or Next.js framework

        npx create-react-app my-app
        cd my-app
        npm start
      
  3. Leave the styling for later. Use a framework that provides ready-to-go solutions regarding the style of components. Bootstrap is a good example for web apps., but there are plenty of others, just pick what you know and feel best. You can also just use raw styling, cause or nothing at all. The only thing you might care about now is the positioning of elements.

    It will look bad, but it still would be better to change it later when you have the UI structure fully available.

  4. Start with a single file (a single component in case of react). Put there all the logic and views. You will split it later. Do not start with the whole project structure, unless you are doing something well-known to you, or are rewriting a project, it will consume too much time.

     export default App = () => (<main>Put things here</main>)
    

Size it properly

I already mentioned that the project should be small. But make sure that it covers common usage topics. Checking out points from the list below will give you an understanding of the main cases, that you might stumble upon in a commercial project.

  1. Fetching data and passing it to UI:

    • You will learn how and when to call external resources and supply data to the component.

      • For React: using useEffect hook with empty dependencies table, calling an asynchronous function inside it and modifying state with the result
    • This will teach you the basics of how the data is represented in the framework and how can it be stored or passed to Frontend.

      • For React: it would teach me a lot about props and state.
    • Just write a simple component and return a string representation of the data you passed to see if it works.

        export default App = (props) => (
        <main>
            Props: { JSON.stringify(props) }
            <br />
            State: { JSON.stringify(stateVariable)}
        </main>)
      
  2. Rendering data: List of data and data details in editable form.

    1. It will make you think about component structure and how different DOM elements can be generated and bound with your data.

      • For React: comes a deeper understanding of jsx/tsx syntax.
    2. Use common HTML elements, you can move them to separate components later.

  3. Talking back to the backend:

    The most common would be to have some forms that post content to REST API.

    But really your task is to learn how to execute some action based on user input. So whatever backend you plan to have, abstract it to a separate service and directly instantiate where needed, or just have a functions module that does the communication in a black-box way.

     export getDataList = (dataRequest) => inMemoryDataList;
     export getDataItem = (id) => inMemoryDataList.find(i => i.id === id);
     export addDataItem = (itemData) => inMemoryDataList.push(itemData);
     // etc...
    

    Focus on processing interaction on the client side:

    • How the actions done on UI are reflected in the code.

      • For React: callbacks on DOM elements events.
    • How they affect the component life-cycle

      • For React: how component lifecycle is constructed and how you can jump into it with different hooks.
    • What is the way to respond to the backend result

      • For React: an old-school way of handling promises, and modifying state in its callbacks.
  4. Handle multiple app states

    Consider different usage scenarios and bring in some UX to it. Take care of cases like success, error (validation or backend) and loading.

    1. You will need to think about the state flow and propagating it to the view.

      • For React: would make you consider the state value field in a single component or split into multiple components and use conditional rendering.

          App = () => {
              switch(status) {
                  case "Error":     return (<div color="red">Bad thing happened :(</div>);
                  case "Loading":   return (<div>Loading...</div>);
                  case "Success":   return (<div color="green">Saved!</div>);
                  default:          return (<form>Form content blah blah...</form>)
              }
          }
        
    2. You will need to figure out of way of validating user input.

    3. It will teach you the way to handle errors

      • For React: catching errors and updating state with it or finding out the differences in class components and their lifecycle hooks.

Bring your experience

Different frameworks and even programming languages are not as siloed as you might think. Don't be afraid to bring your experience from other projects along the way. Whatever you already know, can be and probably will be valuable in this project also.

Try something you know

Do not be afraid to mix concepts and bring your own ideas to the project if you see value in them. You will learn new important things when you dive deeper.

If you come from an OOP environment, then try to extend React's functional architecture with it. In functional programming (React concept takes a lot from it) there is still at some point going to be some state for storing required data. If you have experience in different frameworks, try to use the concepts from it here.

🧠
This may lead to a dead-end, but it will make you more insightful about the technology and capabilities of the framework.

For example, while learning React I asked myself:

  1. Can I do dependency injection in React? Is there a value in it?

    • I learned to use contexts as providers of services to components.

        const userService = useContext<UserService>();
      
        submit(formData) {
            userService.register(formData);
        }
      
  2. Can I use two-way binding of form values like in Vue or Angular?

    • No 'two-way' binding per se, only callbacks for value changes.
  3. What if I use a complex object as a state? How do update only part of it?

    • It led me to useReducer hook and delve a bit deeper into js spread syntax.
  4. Does the react handle asynchronous code? Can I use async await in the component?

    • I learned the proper way of using async await functions inside hooks - defining an async function inside of a hook and calling it there.

        useEffect(() => {
            async function dataReady() {
              const moreData = await getMoreDataApi(data)
              setMoreData(moreData)
            }
          }, [ data ])
        }
      

Do some refactoring

At this stage, you should have the main functionality ready. Now take some time to clean up the code, share common parts and divide responsibilities.

  1. Reuse the code:

    • Create custom hooks, contexts, helper modules etc.
  2. Divide the UI:

    • New component per state + Conditional rendering

    • Small form elements as own components + Component composition

Get into nonfunctional use cases

If there is time still, spend some of it to take care of things like:

  1. Styling

    Now you can make it beautiful if it bothers you. But you also can leave it for now, and use the project later as a base to learn some new styling library.

  2. Performance

    Ask yourself: Can I make it faster? How does it work behind the scenes? Can I leverage something in the framework?

    For example:

    1. I have this form input field attached to the state value. Is this the proper way of doing it? Will it rerender with every input change?

      • Here useRef and useDefferedValue hooks come into play.

          {
          function runSearch() {
            const [searchValue, setSearchValue] = useState("");
            const deferredSearchValue = useDeferredValue(searchValue);
            // ...
          }
          //...
          return (
              <>
                <input value={searchValue} onChange={e => searchValue(e.target.value)} />
                <FilterableDataList searchQuery={deferredSearchValue} />
              </>
            );
          }
        
    2. I call the API every time this component mounts. Can I cache the results somehow knowing it won't change anytime soon?

      • Using useCallback, memo hooks and general concept of functions memoization.
  3. Unhappy scenarios

    Think about different cases where something can go wrong (like very wrong): network issue, configuration error etc. And figure out how to keep the app alive or recoverable if it happens.

    • Introducing error boundaries, thinking about availability to restore the state of a failed app etc.

Final words

Woah! It took some time, didn't it?

As you see, you do not need a complex project or functionality to learn a new framework. There is a huge amount of detail hidden in small things. Just ask yourself the right questions (based on your experience and knowledge) and be ready to explore.

Or maybe follow advice from someone wiser than me, who said it in one line:

TLDR;

“It is not that I'm so smart. But I stay with the questions much longer.”
Albert Einstein

Thank you for reading. Would you consider my way of learning? Would you add or maybe remove something? How do you learn?

Leave a comment or two, and go have fun in your never-ending developer journey.

Best regards!