DEV Community

Cover image for Top React Libraries Every Developer Must Know
Scofield Idehen
Scofield Idehen

Posted on • Originally published at blog.learnhub.africa

Top React Libraries Every Developer Must Know

React is taking over the world of web development - and for good reason. Created by Facebook and released in 2013, React is an open-source JavaScript library for building user interfaces that has revolutionized front-end development.

In this comprehensive guide for beginners, we'll cover all the core concepts you need to know to get up and running with React. You'll learn fundamental topics like:

  • How React works and why it's useful
  • JSX syntax
  • Components, props, and state
  • Handling events
  • The virtual DOM
  • Hooks
  • Working with forms
  • Fetching data
  • Routing

By the end, you'll have a solid grasp of React fundamentals and be ready to build your applications. Let's get started!

How React Works

At its core, React is all about components. A React application comprises multiple reusable components, each responsible for rendering a small part of the overall UI.

For example, you could have a Navbar component, Sidebar component, Form component, etc.

Each component manages its internal state and renders UI based on that state.When the state of a component changes, React will efficiently update and re-render only the components that need to be re-rendered. This is possible thanks to React's use of a virtual DOM.

The virtual DOM is a JavaScript representation of the actual DOM. When a component's state changes, React compares the resulting virtual DOM against the previous virtual DOM.

It then figures out the minimal set of actual DOM manipulations needed to sync them up.

This means you don't have to worry about changing the DOM yourself - React handles it automatically behind the scenes.

This ultimately allows for much faster UI updates than traditional JavaScript apps manually manipulating the DOM.

React also makes use of a one-way data flow. State is passed down from parent components to child components through props.

When state needs to be updated, it's done through callback functions, rather than directly modifying the state.

This unidirectional data flow makes tracking state management in your app easier. It also helps isolate components, since each one works with a local copy of state, rather than relying on global state.

In summary, here are some of the key advantages of React:

  • Declarative - React uses declarative code to render UI based on state rather than imperative code that updates DOM manually.
  • Component-based - Build encapsulated components that manage their own state.
  • Learn once, write anywhere - React can be used for web, mobile, VR, and even native desktop apps.
  • High performance - The virtual DOM makes React extremely fast and efficient.

JSX Syntax

React uses a syntax extension of JavaScript called JSX to describe what the UI should look like. JSX looks like a combination of HTML and JavaScript:

const element = <h1>Hello, world!</h1>;

This syntax is processed into standard JavaScript function calls and objects. Babel is typically used in React apps to convert JSX code into regular JavaScript that browsers can understand.

One key difference is that JSX uses className instead of class for adding CSS classes, since class is a reserved word in JavaScript.

You can embed any valid JavaScript expression inside JSX code by wrapping it with curly braces:

const name = 'John';
const element = <h1>Hello, {name}</h1>;

JSX elements can have attributes just like HTML elements can. However, you can't use keywords like class and for since they are reserved in JavaScript. Instead, React DOM components expect attributes like htmlFor and className:

const element = &lt;div className="container"&gt;
  &lt;label htmlFor="name"&gt;Enter name:&lt;/label&gt;
  &lt;input id="name" /&gt;
&lt;/div&gt;</code></pre>
You can also nest child elements inside a parent JSX element:
<pre><code class="language-javascript">const element = (
  &lt;div&gt;
    &lt;h1&gt;I am the title&lt;/h1&gt;
    &lt;p&gt;This is a paragraph&lt;/p&gt;
  &lt;/div&gt;
)
Enter fullscreen mode Exit fullscreen mode

JSX allows us to write markup that looks like HTML but also lets us use the full power of JavaScript inside that markup. This is what makes React so useful for UI development.

Components, Props, and State

Components are the building blocks of any React app. A component is a self-contained UI piece that encapsulates markup and logic.

Here's an example of a simple Button component:

function Button(props) {
  return &lt;button&gt;{props.text}&lt;/button&gt;;
}
Enter fullscreen mode Exit fullscreen mode

This function accepts props as an argument, accesses the text property on props, and returns JSX that displays a button element.

Components can be either functions or classes. Functional components are simpler since they only need to receive props and return JSX.

Once you have a component, you can render it by passing JSX to ReactDOM.render():

const root = document.getElementById('root');
ReactDOM.render(
  &lt;Button text="Click me"/&gt;,
  root
);
Enter fullscreen mode Exit fullscreen mode

Components can be nested inside other components to build complex UIs:

function App() {
  return (
    &lt;div&gt;
      &lt;Button text="Save" /&gt;
      &lt;Button text="Cancel" /&gt;
    &lt;/div&gt;
  )
}
Enter fullscreen mode Exit fullscreen mode

Props are how data gets passed into components. They are immutable and should not be changed inside the component.

State holds data that can change over time, triggering UI updates. State should be initialized when a component is created:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 0};
  }
}
Enter fullscreen mode Exit fullscreen mode

State should only be modified using setState():

this.setState({count: this.state.count + 1});

Calling setState() triggers React to re-render the component with the new state value. This is how React keeps the UI in sync with data.

Handling Events

Handling events with React elements is similar to handling events with DOM elements. There are a few key syntax differences:

  • React events are named using camelCase instead of lowercase (onclick becomes onClick)
  • You pass a function as the event handler rather than a string

For example, to handle a click event:

function Button(props) {
  function handleClick() {
    console.log('Clicked!');
  }
  return &lt;button onClick={handleClick}&gt;Click Me&lt;/button&gt;
}
Enter fullscreen mode Exit fullscreen mode

Note how handleClick is a normal JS function containing any code you want to run when the element is clicked.

You can also bind event handlers in the constructor:

class Button extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {

    // event handler logic

  }
  render() {
    return &lt;button onClick={this.handleClick}&gt;Click Me&lt;/button&gt;
  }
}
Enter fullscreen mode Exit fullscreen mode

The bind call creates a new function scoped to the component instance. This allows you to access props and state them correctly inside the handler.

You can pass custom arguments to event handlers, too:

<button onClick={() => this.handleClick(id)} />

This is useful for passing the id of the element or other data.

The Virtual DOM

One of the core features that makes React so performant is its use of a virtual DOM.

Let's think about how UI updates work without a virtual DOM. When state changes, React would have to manipulate the actual DOM to change what's rendered directly. This can be slow for apps with large DOMs and frequent updates.

Instead, React maintains a lightweight virtual representation of the UI in memory. This virtual DOM is an abstraction layer between React components and the actual DOM.

When state changes in a component, React creates a new virtual DOM tree by combining the component trees of the app.

It then compares the new virtual DOM against the previous virtual DOM. This process is called "diffing".

React figures out exactly which virtual DOM nodes have changed through this diffing process. Finally, React only updates those changed DOM nodes in the real DOM.

Since the virtual DOM can update quickly without touching the real DOM, performance is significantly improved.

React must only make targeted updates to the real DOM rather than re-rendering everything from scratch. This makes the re-rendering process faster and more efficient.

The developer doesn't have to think about the virtual DOM at all. It's an implementation detail handled entirely by React. However understanding how it works under the hood can help explain React's performance benefits.

Hooks

Hooks were introduced in React 16.8 to use state, and other React features in functional components.

Before hooks, functional components could only render UI based on their props - they lacked capabilities like state that only class components had.

Hooks allow function components to do everything classes can do except for features like context and lifecycle methods. Some commonly used built-in hooks include:

useState: Adds state to function components:

import { useState } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  return (
    &lt;div&gt;
      &lt;p&gt;You clicked {count} times&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
        Click me
      &lt;/button&gt;
    &lt;/div&gt;
  );
}
Enter fullscreen mode Exit fullscreen mode

useEffect: Adds the ability to perform side effects from function components:

import { useState, useEffect } from 'react';
function Counter() {
  const [count, setCount] = useState(0);
  useEffect(() =&gt; {
    document.title = You clicked ${count} times;
  });
  return ( 
    //...
  )
}
Enter fullscreen mode Exit fullscreen mode

useContext: Consume context from a function component:

const ThemeContext = React.createContext('light');
function Button() {
  const theme = useContext(ThemeContext);
  return (
    &lt;button className={theme}&gt;OK&lt;/button&gt;
  );
}
Enter fullscreen mode Exit fullscreen mode

Along with built-in hooks, you can create your custom hooks to share reusable logic.

Working with Forms

Form handling in React involves:

  • Adding state to track form input values
  • Listening for change events on inputs to update that state
  • Accessing values from state when rendering to set input values

For example:

class Form extends React.Component {
  state = {name: ''};
  handleChange = (e) =&gt; {
    this.setState({name: e.target.value})
  }
  render() {
    return (
      &lt;&gt;
        &lt;input 
          value={this.state.name}
          onChange={this.handleChange} 
        /&gt;
        &lt;p&gt;{this.state.name}&lt;/p&gt;
      &lt;/&gt;
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

Controlled vs Uncontrolled Components

React forms can use either controlled or uncontrolled components:

  • Controlled: Value handled by React state
  • Uncontrolled: Value handled by DOM itself

With uncontrolled components, you use refs to access DOM input values instead of state directly.

Handling Multiple Inputs

You can track state for each input separately:

state = {
  name: '',
  email: '' 
};
handleNameChange = (e) =&gt; {
  this.setState({name: e.target.value});
}
handleEmailChange = (e) =&gt; {
  this.setState({email: e.target.value});  

}


render() {
  return (
    &lt;&gt;
      &lt;input 
        value={this.state.name}
        onChange={this.handleNameChange}
      /&gt; 
      &lt;input
        value={this.state.email}
        onChange={this.handleEmailChange}
      /&gt;
    &lt;/&gt;
  )
}
Enter fullscreen mode Exit fullscreen mode

Or manage state as a single object:

state = {

  formData: {

    name: '',

    email: ''

  }

};


handleChange = (e) =&gt; {

  this.setState({

    formData: {

      ...this.state.formData,

      [e.target.name]: e.target.value

    } 

  });

}


render() {

  return (

    &lt;&gt;

     &lt;input 

       name="name"

       value={this.state.formData.name}

       onChange={this.handleChange}

     /&gt;

     // ...

    &lt;/&gt;

  )

}
Enter fullscreen mode Exit fullscreen mode

This uses computed property names to update just one key in formData.

Handling Submits

Use a submit handler that prevents default submit, then calls a function to handle form values:

handleSubmit = (e) =&gt; {
  e.preventDefault();
  this.processForm();
}
processForm() {

  // send data to server  

}
render() {
  return (
    &lt;form onSubmit={this.handleSubmit}&gt;
      // inputs 
      &lt;button&gt;Submit&lt;/button&gt;
    &lt;/form&gt;
  )
}

Enter fullscreen mode Exit fullscreen mode

Validation

There are libraries like Formik that help with validation. You can also validate on submit:

handleSubmit = (e) =&gt; {

  e.preventDefault();

  // validate form 

  if(valid) { 

    this.processForm();

  }

}
Enter fullscreen mode Exit fullscreen mode

Display validation errors to user by tracking them in state.

Fetching Data

The useEffect hook can be used to fetch data on mount and on state changes:

function MyComponent() {
  const [data, setData] = useState(null);
  useEffect(() =&gt; {
    fetch('/some-api')
      .then(res =&gt; res.json())
      .then(setData);
  }, []); // empty deps = only on mount
  //...
}
Enter fullscreen mode Exit fullscreen mode

The empty array means this effect will only run once on mount, not on re-renders.

You can also fetch on state changes:

useEffect(() =&gt; {
  // refetch data
}, [someStateVar]);
Enter fullscreen mode Exit fullscreen mode

Now, it'll re-run if someStateVar changes.

  • Handling Loading State

While fetching, data will be null. You can track state like:

const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
useEffect(() =&gt; {
  setLoading(true);
  fetchData().then(data =&gt; {
    setData(data);
    setLoading(false);
  })
}, [])
Enter fullscreen mode Exit fullscreen mode

Then check loading before displaying data:

return (
  {loading &amp;&amp; &lt;p&gt;Loading...&lt;/p&gt;}
  {data &amp;&amp; &lt;DisplayData data={data} /&gt;}
)
Enter fullscreen mode Exit fullscreen mode
  • Error Handling

Handle errors by adding catch:

useEffect(() =&gt; {
  setLoading(true);
  fetchData()
    .then(setData)
    .catch(error =&gt; {
      // handle error  
    })
    .finally(() =&gt; setLoading(false))
}, [])
Enter fullscreen mode Exit fullscreen mode

Or use try/catch:

useEffect(() =&gt; {
  const fetchData = async () =&gt; {
    try {
      setLoading(true);
      const data = await fetchData();
      setData(data);
    } catch (error) {
      // handle error
    } finally {
      setLoading(false); 
    }
  }
  fetchData();
}, [])
Enter fullscreen mode Exit fullscreen mode

Track error state to display to user.

Routing

For routing in React, the React Router library is commonly used.

First, wrap components with a <Router> component.

Then use <Link> to create links instead of anchor tags:

<Link to="/about">About</Link>

And use <Route> to define routes:

<Route exact path="/" component={Home} />
<Route path="/about" component={About} />

exact only matches if path is exactly "/".

Route components receive history, location, and match props.

The component for the matching route will render.

Router can use push and replace to navigate:

history.push('/about')

Route parameters:

&lt;Route path="/user/:id" component={User} /&gt;

// User component

const { id } = this.props.match.params;</code></pre>
Query strings:
<pre><code class="language-javascript">&lt;Link to="/posts?sortBy=newest" /&gt;

// Get search string

const { search } = this.props.location;

// ?sortBy=newest


// Parse with query-string pkg 

import queryString from 'query-string';

const { sortBy } = queryString.parse(search); 

// newest
Enter fullscreen mode Exit fullscreen mode

Nested routes:

&lt;Route path="/users" component={Users}&gt;
  &lt;Route path=":id" component={User} /&gt;
&lt;/Route&gt;
Enter fullscreen mode Exit fullscreen mode

Redirects:

<Redirect from="/old-path" to="/new-path" />

Conditionals:

&lt;Route 
  path="/dashboard"
  render={() =&gt; (
    loggedIn ? (
      &lt;Dashboard /&gt;  
    ) : (
      &lt;Redirect to="/login" /&gt;
    )
  )}
/&gt;
Enter fullscreen mode Exit fullscreen mode

Handling 404s:

&lt;Switch&gt;
  &lt;Route exact path="/" /&gt;
  &lt;Route component={NotFound} /&gt; 
&lt;/Switch&gt;
Enter fullscreen mode Exit fullscreen mode

Programmatic navigation:

const history = useHistory();
history.push('/login');
Enter fullscreen mode Exit fullscreen mode

Conclusion

And that covers the core basics of React! With this foundation, you should be ready to start building your applications.

The key takeaways include:

  • React is all about modular, reusable components
  • JSX mixes HTML and JavaScript for declaring UI
  • Props pass data into components, state holds data that changes over time
  • The virtual DOM improves performance by minimizing DOM updates

I hope you enjoyed reading this guide and feel motivated to start your Python programming journey.

If you find this post exciting, find more exciting posts on Learnhub Blog; we write everything tech from Cloud computing to Frontend Dev, Cybersecurity, AI, and Blockchain.

Resource

Top comments (2)

Collapse
 
respect17 profile image
Kudzai Murimi

Thanks for taking the time to share your knowledge with the community. Well-documented POST.

Collapse
 
scofieldidehen profile image
Scofield Idehen

Thanks a lot, I really need the motivation.