DEV Community

loading...
Cover image for 5 Epic React Tips To Use Today

5 Epic React Tips To Use Today

Reed Barger
Full-stack React developer, sharing cheatsheets, articles, and premium courses to help you get ahead @ ReactBootcamp.com
Originally published at reedbarger.com ・6 min read

Here's a list of amazing tricks that you can use to improve your React applications instantly.

These tips will not only make your code cleaner and more reliable, but also aim to make your development experience easier and overall more enjoyable.

Give these techniques a try in your React projects today!

Want the complete guide to become an expert React developer from front to back? Check out The React Bootcamp.

Replace Redux with React Query

As our application gets larger it becomes harder to manage state across our components, we may reach for a state management library like Redux.

If our application relies on data that we get from an API, we often use Redux to fetch that server state and then update our application state.

This can be a challenging process; not only do you have to fetch data, but you also need to handle the different states, depending on whether you have the data or are in a loading or error state.

Instead of using Redux to manage data you get from a server, use a library like React Query.

React Query not only gives you greater control over making HTTP requests in your React apps through helpful hooks and the ability to easily refetch data, but it also enables us to seamlessly manage state across our app components, often without having to manually update state ourselves.

Here's how you set up React Query in your index.js file:

import { QueryClient, QueryClientProvider } from 'react-query'
import ReactDOM from "react-dom";

import App from "./App";

const queryClient = new QueryClient()

const rootElement = document.getElementById("root");
ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  rootElement
);
Enter fullscreen mode Exit fullscreen mode

Here we are setting up a query client which will setup a cache for us to effortlessly manage any requests that we have made in the past, plus a query client provider component to pass it down the entire component tree.

How do you start making requests with React Query?

You can do so with the useQuery hook, which takes an identifier for our query (in this case, since we are fetching user data, we will call it 'user'), plus a function that is used to fetch that data.

import { useQuery } from "react-query";

export default function App() {
  const { isLoading, isError, data } = useQuery("user", () =>
    fetch("https://randomuser.me/api").then((res) => res.json())
  );

  if (isLoading) return "Loading...";
  if (isError) return "Error!";

  const user = data.results[0];
  return user.email;
}
Enter fullscreen mode Exit fullscreen mode

As you can see, React Query takes care of managing these various states that can take place when we fetch our data. We no longer need to manage these states ourselves, we can just destructure them from what is returned from useQuery.

Where does the state management part of useQuery come into play?

Now that we have fetched the user data and have it stored in our internal cache, all we need to do to be able to use it across any other component is to call useQuery() with the 'user' key that we associated with it:

import { useQuery } from "react-query";

export default function OtherComponent() {
  const { data } = useQuery('user');

  console.log(data);
}
Enter fullscreen mode Exit fullscreen mode

Make React Context Easier with a Custom Hook

React Context is a great way to pass data across our component tree. It allows us to pass data into whatever component we like without having to use props.

To consume context in a React function component, we use the useContext hook.

However, there is a slight downside to doing so. In every component that we want to consume data that has been passed down on context, we have to import both the created context object and import React to grab the useContext hook.

Instead of having to write multiple import statements every time we want to read from context, we can simply create a custom React hook.

import React from "react";

const UserContext = React.createContext();

function UserProvider({ children }) {
  const user = { name: "Reed" };
  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}

function useUser() {
  const context = React.useContext(UserContext);
  if (context === undefined) {
    throw new Error("useUser in not within UserProvider");
  }
  return context;
}

export default function App() {
  return (
    <UserProvider>
      <Main />
    </UserProvider>
  );
}

function Main() {
  const user = useUser();

  return <h1>{user.name}</h1>; // displays "Reed"
}
Enter fullscreen mode Exit fullscreen mode

In this example, we are passing down user data on our custom UserProvider component, which takes a user object and is wrapped around the Main component.

We have a useUser hook to more easily consume that context. We only need to import that hook itself to consume our User Context in any component we like, such as our Main component.

Manage Context Providers in a Custom Component

In almost any React application that you create, you will need a number of Context providers.

We not only need Context providers not only for React Context that we are creating, but also from third party libraries that rely upon it (like React Query) in order to pass their tools down to our to the components that need them.

Once you've started working on your React project for a while, here's what it tends to look like:

ReactDOM.render(
  <Provider3>
    <Provider2>
      <Provider1>
        <App />
      </Provider1>
    </Provider2>
  </Provider3>,
  rootElement
);
Enter fullscreen mode Exit fullscreen mode

What can we do about this clutter?

Instead of putting all of our context providers within our App.js file or index.js file, we can create a component called ContextProviders.

This allows us to use the children prop, then all we have to do is put all these providers into this one component:

src/context/ContextProviders.js

export default function ContextProviders({ children }) {
  return (
    <Provider3>
      <Provider2>
        <Provider1>
          {children}
        </Provider1>
      </Provider2>
    </Provider3>
  );
}
Enter fullscreen mode Exit fullscreen mode

Then, wrap the ContextProviders component around App:

src/index.js

import ReactDOM from "react-dom";
import ContextProviders from './context/ContextProviders'
import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <ContextProviders>
    <App />
  </ContextProviders>,
  rootElement
);
Enter fullscreen mode Exit fullscreen mode

Pass props easier using the object spread operator

When it comes to working with components, we normally pass down data with the help of props. We create a prop name and setting it equal to its appropriate value.

However, if we have a lot of props that we need to pass down to a component, do we need to list them all individually?

No, we don't.

A very easy way to be able to pass down all the props that we like without having to write all of the prop names and their corresponding values is to use the {...props} pattern.

This involves putting all of our prop data in an object and spreading all of those props individually to the component we want to pass it to:

export default function App() {
  const data = {
    title: "My awesome app",
    greeting: "Hi!",
    showButton: true
  };

  return <Header {...data} />;
}

function Header(props) {
  return (
    <nav>
      <h1>{props.title}</h1>
      <h2>{props.greeting}</h2>
      {props.showButton && <button>Logout</button>}
    </nav>
  );
}
Enter fullscreen mode Exit fullscreen mode

Map over fragments with React fragment

The .map() function in React allows us to take an array and iterate over it, then display each elements data within some JSX.

However, in some cases, we want to iterate over that data but we do not want to return it within a closing JSX element. Maybe using an enclosing JSX element would modify our applied or we simply don't want to add another element to the DOM.

A little known tip to be able to iterate over a set of data, not have the parent element as an HTML element is to use React.Fragment.

To use the longhand form of React fragments allows us can provide it the key prop which is required for any element over which we are iterating.

import React from 'react'

export default function App() {
  const users = [
    {
      id: 1,
      name: "Reed"
    },
    {
      id: 2,
      name: "John"
    },
    {
      id: 3,
      name: "Jane"
    }
  ];

  return users.map((user) => (
    <React.Fragment key={user.id}>{user.name}</React.Fragment>
  ));
}
Enter fullscreen mode Exit fullscreen mode

Note that we cannot use the required key prop for the shorthand fragments alternative: <></>.

Want Even More? Join The React Bootcamp

The React Bootcamp was created to make you a superstar, job-ready React developer in 1 amazing course, featuring videos, cheatsheets and much more.

Gain the insider information 100s of developers have already used to become React experts, find their dream jobs, and take control of their future:

The React Bootcamp

Click here to be notified when it opens

Discussion (3)

Collapse
spiropoulos94 profile image
NikosSp

React query is trully amazing, nice post!

Collapse
dev_emmy profile image
nshimiye_emmy

great, thanks!!!

Collapse
hmarques98 profile image
Henrique Marques

Nice post. Brilliant. Thanks!!!