react.js

How to Get the Value of an Input When a Button is Clicked in React

Related: How to Get an Input Field’s Value in React

To get the value of an input field on button click in React:

  1. Create a state variable to store the value of the input field.
  2. Set an onChange event handler on the input to update the state variable when the input field value changes.
  3. Set an onClick event handler on a button element.
  4. Access the state variable in the event handler.

For example:

App.js

import { useState } from 'react';

export default function App() {
  const [message, setMessage] = useState('');

  const [updated, setUpdated] = useState(message);

  const handleChange = (event) => {
    setMessage(event.target.value);
  };

  const handleClick = () => {
    // 👇 "message" stores input field value
    setUpdated(message);
  };

  return (
    <div>
      <input
        type="text"
        id="message"
        name="message"
        onChange={handleChange}
        value={message}
      />

      <h2>Message: {message}</h2>

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}
Getting the input value on button click.

With the useState() hook we create a state variable (message) to store the current value of the input field. We also create another state variable (updated) that will be updated with the input field value when the button is clicked.

We set an onChange event handler on the input field to make this handler get called whenever the input value changes. In the handler, we use the event.target property to access the object representing the input element. The value property of this object contains the input value, so we pass it to setMessage() to update message, and this reflects on the page.

After setting up the controlled input, we can now use message outside the handleChange handler to access the current value of the input field.

So in the onClick event handler we set on the button, we use setUpdated(message) to update the updated variable with the current input field value.

Get value of uncontrolled input on button click

To get the value of an uncontrolled input on button click in React:

  1. Create a ref for the input field
  2. Set an onClick event handler on the button.
  3. Use the ref object to access the current input value in the event handler.

For example:

App.js

import { useRef, useState } from 'react';

export default function App() {
  const inputRef = useRef(null);

  const [updated, setUpdated] = useState('');

  const handleClick = () => {
    // 👇 "inputRef.current.value" is input value
    setUpdated(inputRef.current.value);
  };

  return (
    <div>
      <input
        ref={inputRef}
        type="text"
        id="message"
        name="message"
      />

      <h2>Updated: {updated}</h2>

      <button onClick={handleClick}>Update</button>
    </div>
  );
}
Updating text with the value of an input field on button click.

While the data in a controlled input is handled by React state, the data in an uncontrolled input is handled by the DOM itself. This is why the input in the example above doesn’t have a value prop or onChange event handler set. Instead, we access the input field value with a React ref. The DOM updates this value when the text in the input is changed.

We create a ref object with the useRef() hook and set it to the ref prop of the input. Doing this sets the current property of the ref object to the DOM object that represents the input element.

useRef() returns a mutable ref object that does not change value when a component is updated. Also, modifying the value of this object’s current property does not cause a re-render. This is in contrast to the setState update function returned from useState().

Although the React documentation recommends using controlled components, uncontrolled components offer some advantages. You might prefer them if the form is very simple and doesn’t need instant validation, and values only need to be accessed when the form is submitted.

How to Link an Image in React

Related: How to Use an Image as a Link in React

To link a local image in React, import the image at the top of the file and assign it to the src prop of an img element.

For example:

App.js

// 👇 import image from file
import myImage from './my-image.jpg';

export default function App() {
  return (
    <div>
      {/* 👇 show image */}
      <img src={myImage} alt="Trees" height="200" />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}
Linking and displaying an image on the webpage.
Linking and displaying an image on the webpage.

This approach works when using a Webpack-based tool like Create React App.

Note that the image file must be within the project directory to be imported successfully. An error will occur if the file is outside the project directory.

Alternatively, we can use the require() function to link an image in React.

The following code example will produce precisely the same result on the page as the first example.

App.js

export default function App() {
  return (
    <div>
      {/* 👇 */}
      <img
        src={require('./my-image.jpg')}
        alt="Trees"
        height="200"
      />

      <br />
      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

The advantage require() has here is that it doesn’t need to be at the top of the page. We can simply assign the result of require() to the src prop without having to store it in a variable.

Another way to link an image in React is to place it in the public folder and reference it with its relative path.

For example, if we placed the my-image.png file in the public folder, we’ll be able to display it in the page like this:

App.js

export default function App() {
  return (
    <div>
      {/* 👇 show image */}
      <img src="./my-image.jpg" alt="Trees" height="200" />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

Using the public folder is advantageous when we have many images that we want to display dynamically.

In the following examples, we dynamically display 100 images placed in a grid subfolder under public, and named with a certain pattern (image-1.jpg, image-2.jpg, …, image-100.png) in a grid.

App.js

export default function App() {
  return (
    <div>
      <div
        style={{
          display: 'grid',
          gridTemplateColumns:
            'repeat(auto-fit, minmax(min-content, 250px))',
          gap: '8px',
        }}
      >
        {[...Array(100)].map((_, i) => {
          return (
            <div>
              {/* 👇 linking images dynamically */}
              <img
                key={i}
                src={`./grid/image-${i + 1}.jpg`}
                style={{ width: '100%', height: 'auto' }}
              />
            </div>
          );
        })}
      </div>
    </div>
  );
}

If the image is stored online, then we’ll just have to set the URL of the image to the src prop to link and display it, like we do in plain HTML.

App.js

export default function App() {
  return (
    <div>
      {/* 👇 show remote image */}
      <img
        src="http://example.com/trees/my-image.jpg"
        alt="Trees"
        height="200"
      />

      <br />

      <span
        style={{
          color: 'green',
          fontSize: '1.2em',
          fontWeight: 'bold',
        }}
      >
        Trees
      </span>
    </div>
  );
}

3 Easy Ways to Make Any Text Bold in React

To make text bold in React, wrap the text with a span element, and set the fontWeight style property of the span to bold.

For example:

App.js

export default function App() {
  return (
    <div>
      Coding{' '}
      <span style={{ fontWeight: 'bold' }}>Beauty</span>
    </div>
  );
}
Making text bold in React

We used inline styles to make the text bold. The style attribute of a React element accepts a JavaScript object with camelCased properties instead of a CSS kebab-cased string. So, fontWeight sets the font-weight CSS property.

If we don’t need to control the boldness with a condition, then we can just wrap the text with a b element.

App.js

export default function App() {
  return (
    <div>
      Coding <b>Beauty</b>
    </div>
  );
}

Conditionally bold text with inline styles

Sometimes we might want to make a piece of text bold only if a certain condition is true. Here’s how we can do this:

App.js

import { useState } from 'react';

export default function App() {
  const [bold, setBold] = useState(false);

  const handleBoldChange = (event) => {
    setBold(event.target.checked);
  };

  return (
    <div>
      Coding{' '}
      <span
        style={{ fontWeight: bold ? 'bold' : 'normal' }}
      >
        Beauty
      </span>

      <br></br>

      <input
        name="bold"
        type="checkbox"
        value={bold}
        onChange={handleBoldChange}
      ></input>

      <label htmlFor="bold">Bold</label>
    </div>
  );
}
The text is bold only if the checkbox is checked.

We use a state variable named bold to store the current checked state of the checkbox and to determine whether the relevant text should be bold or not.

We attach an event listener to the onChange event, so it is called when the checkbox is checked or unchecked. In this listener, we use the setBold function to update the value of bold and change the boldness of the text.

Bold text with custom component

If we frequently need make text bold, we can abstract the logic into a reusable custom component.

App.js

function BoldText({ children }) {
  return (
    <span style={{ fontWeight: 'bold' }}>{children}</span>
  );
}

export default function App() {
  return (
    <div>
      Coding <BoldText>Beauty</BoldText>
    </div>
  );
}

This code will produce the same result on the web page.

Whatever text is place within the <BoldText> and </BoldText> tags will have a bold font.

Conditionally bold text with custom component

To make text bold conditionally with a custom component, we can create a boolean bold property that will determine whether the child text of the component should be bold or not.

App.js

import { useState } from 'react';

function BoldText({ children, bold }) {
  return (
    <span style={{ fontWeight: bold ? 'bold' : 'normal' }}>
      {children}
    </span>
  );
}

export default function App() {
  const [bold, setBold] = useState(false);

  const handleBoldChange = (event) => {
    setBold(event.target.checked);
  };

  return (
    <div>
      Coding <BoldText bold={bold}>Beauty</BoldText>

      <br></br>

      <input
        name="bold"
        type="checkbox"
        value={bold}
        onChange={handleBoldChange}
      ></input>

      <label htmlFor="bold">Bold</label>
    </div>
  );
}
The text is bold only if the checkbox is checked.

Bold text with class

Alternatively, we can make text bold in React by defining a bold class in a CSS file, e.g., App.css:

App.css

.bold {
  font-weight: bold;
}

We would then import the App.css file and apply the bold class to a span element to make all the text within it bold.

App.js

import './App.css';

export default function App() {
  return (
    <div>
      Coding <span className="bold">Beauty</span>
    </div>
  );
}

And this would produce exactly the same result as the previous two methods:

Conditionally bold text with class

Here’s how we would use a class name to make text bold only if a particular condition is true:

App.js

import { useState } from 'react';
import './App.css';

export default function App() {
  const [bold, setBold] = useState(false);

  const handleBoldChange = (event) => {
    setBold(event.target.checked);
  };

  return (
    <div>
      Coding{' '}
      <span className={bold ? 'bold' : ''}>Beauty</span>

      <br></br>

      <input
        name="bold"
        type="checkbox"
        value={bold}
        onChange={handleBoldChange}
      ></input>
      
      <label htmlFor="bold">Bold</label>
    </div>
  );
}

Using the ternary operator, we set the className property to the bold class if the bold variable is true. Otherwise, we set className to an empty string ('').

The text is bold only if the checkbox is checked.

Tip: Instead of the ternary operator, you can use the clsx utility from NPM to more easily construct class names from a set of conditions in React.

How to Remove an Element On Click in React

In this article, we’ll learn how to easily remove an element onclick in React, whether it’s in a list or it’s a standalone element.

Remove stand-alone element onclick in React

To remove a stand-alone element onclick:

  1. Store the visibility state in a state variable as a Boolean value, and use its value to conditionally render the element.
  2. Attach an event handler to the onClick event of the element.
  3. In the event handler, negate the value of the visibility state to remove the element from the DOM.

One example should make this clear:

import { useState } from 'react';

export default function App() {
  const [visible, setVisible] = useState(true);

  const removeElement = () => {
    setVisible((prev) => !prev);
  };

  return (
    <div>
      Click to remove element
      <br />
      {visible && (
        <button onClick={removeElement}>Remove</button>
      )}
    </div>
  );
}
Removing an element onclick in React

We use the useState() to create a state variable in the component. This hook returns an array of two variables, generally called state and setState. The state variable (visible) holds the current visibility state, and the setState function (setVisible) updates it.

const [visible, setVisible] = useState(true);

We set an event handler to the onClick event of the button, so when the button is clicked, the handler function will be called.

<button onClick={removeElement}>Remove</button>

In the handler function, we use the setState function for the visibility state to update the state.

const removeElement = () => {
  setVisible((prev) => !prev);
};

Instead of passing the negated value directly, we pass a callback function to setState that returns the negated value. This ensures that we always get the most recent state value.

Tip

React batches state changes for performance reasons, so the state may not be updated immediately after setState is called, in the order we might expect. This is why we always pass a function to setState when the new state is computed from the data of the previous state.

Remove element from list onclick

To remove an element from a list onclick:

  1. Attach an event handler to the onClick event of every element in the array representing the list.
  2. In the event handler for a particular element, call the filter() method on the array, specifying a condition that is true for every element in the array apart from the one to be removed.
  3. Use setState to update the state array with the result returned from filter().

For example:

import { useState } from 'react';

export default function App() {
  const [fruits, setFruits] = useState([
    'Orange',
    'Banana',
    'Apple',
  ]);

  const removeElement = (index) => {
    const newFruits = fruits.filter((_, i) => i !== index);
    setFruits(newFruits);
  };

  return (
    <div>
      {fruits.map((fruit, index) => (
        <div key={index}>
          <button
            onClick={() => removeElement(index)}
          >
            {fruit}
          </button>
          <br />
          <br />
        </div>
      ))}
    </div>
  );
}
Removing an element from a list onclick in React
Removing an element from a list onclick

With the map() method, we render a button for each element in the array. For each button, we attach an event handler that will call the removeElement() method, passing as an argument the index of the element that the button represents.

{fruits.map((fruit, index) => (
  <div key={index}>
    <button
      onClick={() => removeElement(index)}
    >
      {fruit}
    </button>
    <br />
    <br />
  </div>
))}

removeElement() removes an element by returning a condition from the filter() callback that is true only for elements in the array that don’t have the index passed to removeIndex(). Doing this excludes the element with that index from the array, so when the array state is updated, the button representing that element is no longer rendered.

const fruits = ['Orange', 'Banana', 'Apple'];

const newFruits = fruits.filter((_, index) => index !== 1);

console.log(newFruits); // [ 'Orange', 'Apple' ]

Note: don’t modify state directly in React

Trying to remove the element from the array by modifying it using a function like splice() will not work:

const removeElement = (index) => {
  // ⚠️ Mutating the array like this will not update the view
  fruits.splice(index, 1);
};

State is meant to be immutable in React, so we can’t update the array by mutating it. It has to be replaced with a new array returned from filter() for the view to update.

Remove object element from list onclick

We can also use this approach to remove an element represented by an object from a list onclick.

import { useState } from 'react';

export default function App() {
  const [fruits, setFruits] = useState([
    { id: 1, name: 'Orange' },
    { id: 2, name: 'Banana' },
    { id: 3, name: 'Apple' },
  ]);

  const removeElement = (id) => {
    const newFruits = fruits.filter(
      (fruit) => fruit.id !== id
    );
    setFruits(newFruits);
  };

  return (
    <div>
      {fruits.map((fruit) => (
        <div key={fruit.id}>
          <button onClick={() => removeElement(fruit.id)}>
            {fruit.name}
          </button>
          <br />
          <br />
        </div>
      ))}
    </div>
  );
}

Instead of filtering by index, this time we filter by the id property to remove an item from the array and remove the element from the list in the DOM.

const fruits = [
  { id: 1, name: 'Orange' },
  { id: 2, name: 'Banana' },
  { id: 3, name: 'Apple' },
];

const newFruits = fruits.filter((fruit) => fruit.id !== 2);

console.log(newFruits);
// [ { id: 1, name: 'Orange' }, { id: 3, name: 'Apple' } ]

How to Use an Async Function in the React useEffect() Hook

In this article, we’ll look at different ways to easily call an async function inside the React useEffect() hook, along with pitfalls to avoid when working with async/await.

Call async Functions With then/catch in useEffect()

async functions perform an asynchronous operation in JavaScript. To wait for the Promise the async function returns to be settled (fulfilled or rejected) in the React useEffect() hook, we could use its then() and catch() methods:

In the following example, we call the fetchBooks() async method to fetch and display stored books in a sample reading app:

export default function App() {
  const [books, setBooks] = useState([]);

  useEffect(() => {
    // await async "fetchBooks()" function
    fetchBooks()
      .then((books) => {
        setBooks(books);
      })
      .catch(() => {
        console.log('Error occured when fetching books');
      });
  }, []);

  return (
    <div>
      {books.map((book) => (
        <div>
          <h2>{book.title}</h2>
        </div>
      ))}
    </div>
  );
}

async/await Problem: async Callbacks Can’t Be Passed to useEffect()

Perhaps you would prefer to use the async/await syntax in place of then/catch. You might try doing this by making the callback passed to useEffect() async.

This isn’t a good idea though, and if you’re using a linter it will inform you of this right away.

// ❌ Your linter: don't do this!
useEffect(async () => {
  try {
    const books = await fetchBooks();
    setBooks(books);
  } catch {
    console.log('Error occured when fetching books');
  }
}, []);

Your linter complains because the first argument of useEffect() is supposed to be a function that either returns nothing or returns a function to clean up side effects. But async functions always return a Promise (implicitly or explicitly), and Promise objects can’t be called as functions. This could cause real issues in your React app, such as memory leaks.

useEffect(async () => {
  const observer = () => {
    // do stuff
  };

  await fetchData();

  observable.subscribe(observer);

  // Memory leak!
  return () => {
    observable.unsubscribe(observer);
  };
}, []);

In this example, because the callback function is async, it doesn’t actually return the defined clean-up function, but rather a Promise object that is resolved with the clean-up function. Hence, this clean-up function is never called, and the observer is never unsubscribed from the observable, resulting in a memory leak.

So how can we fix this? How can we use the await operator with an async function in the useEffect() hook?

async/await Solution 1: Call async Function in IIFE

One straightforward wait to solve this problem is to await the async function in an immediately invoked function expression (IIFE):

const [books, setBooks] = useState([]);

useEffect(() => {
  (async () => {
    try {
      const books = await fetchBooks();
      setBooks(books);
    } catch (err) {
      console.log('Error occured when fetching books');
    }
  })();
}, []);

As the name suggests, an IIFE is a function that runs as soon as it is defined. They are used to avoid polluting the global namespace and in scenarios where trying an await call could cause problems in the scope containing the IIFE (e.g., in the useEffect() hook, or in the top-level scope for pre-ES13 JavaScript).

async/await Solution 2: Call async Function in Named Function

Alternatively, you can await the async function inside a named function:

useEffect(() => {

  // Named function "getBooks"
  async function getBooks() {
    try {
      const books = await fetchBooks();
      setBooks(books);
    } catch (err) {
      console.log('Error occured when fetching books');
    }
  }

  // Call named function
  getBooks();
}, []);

Remember the example using the observable pattern? Here’s how we can use a named async function to prevent the memory leak that occurred:

// ✅ Callback is not async
useEffect(() => {
  const observer = () => {
    // do stuff
  };

  // Named function "fetchDataAndSubscribe"
  async function fetchDataAndSubscribe() {
    await fetchData();
    observable.subscribe(observer);
  }

  fetchDataAndSubscribe();

  // ✅ No memory leak
  return () => {
    observable.unsubscribe(observer);
  };
}, []);

async/await Solution 3: Create Custom Hook

We can also create a custom hook that behaves similarly to useEffect() and can accept an async callback without causing any issues.

The custom hook could be defined this way:

export function useEffectAsync(effect, inputs) {
  useEffect(() => {
    return effect();
  }, inputs);
}

And we’ll be able to call it from multiple places in our code like this:

const [books, setBooks] = useState([]);

useEffectAsync(async () => {
  try {
    const books = await fetchBooks();
    setBooks(books);
  } catch (err) {
    console.log('Error occured when fetching books');
  }
});

With these three approaches, we can now easily use the await operator with async functions in the useEffect() hook.

Define Async Function Outside useEffect()

To define a named async function outside the useEffect() hook, you can wrap the function with the useCallback() hook:

const getBooks = useCallback(async () => {
  try {
    const books = await fetchBooks();
    setBooks(books);
  } catch (err) {
    console.log('Error occured when fetching books');
  }
}, []);

useEffect(() => {
  getBooks();
}, [getBooks]);

Without useCallback(), the getBooks() function will be re-created on every re-render, triggering useEffect() and causing performance problems.

How to Use Async / Await in the React useEffect() Hook

To await an async function in the React useEffect() hook, wrap the async function in an immediately invoked function expression (IIFE).

For example:

const [books, setBooks] = useState([]);

useEffect(() => {
  (async () => {
    try {
      // await async "fetchBooks()" function
      const books = await fetchBooks();
      setBooks(books);
    } catch (err) {
      console.log('Error occured when fetching books');
    }
  })();
}, []);

In this article, we’ll look at different ways to call an async function in the useEffect() hook, along with pitfalls to avoid when working with async/await.

Calling async Functions With then/catch in useEffect()

async functions perform an asynchronous operation in JavaScript. To wait for the Promise the async function returns to be settled (fulfilled or rejected) in the React useEffect() hook, we could use its then() and catch() methods:

In the following example, we call the fetchBooks() async method to fetch and display stored books in a sample reading app:

export default function App() {
  const [books, setBooks] = useState([]);

  useEffect(() => {
    // await async "fetchBooks()" function
    fetchBooks()
      .then((books) => {
        setBooks(books);
      })
      .catch(() => {
        console.log('Error occured when fetching books');
      });
  }, []);

  return (
    <div>
      {books.map((book) => (
        <div>
          <h2>{book.title}</h2>
        </div>
      ))}
    </div>
  );
}

async/await Problem: async Callbacks Can’t Be Passed to useEffect()

Perhaps you would prefer to use the async/await syntax in place of then/catch. You might try doing this by making the callback passed to useEffect() async.

This isn’t a good idea though, and if you’re using a linter it will inform you of this right away.


// ❌ Your linter: don't do this!
useEffect(async () => {
  try {
    const books = await fetchBooks();
    setBooks(books);
  } catch {
    console.log('Error occured when fetching books');
  }
}, []);

Your linter complains because the first argument of useEffect() is supposed to be a function that either returns nothing or returns a function to clean up side effects. But async functions always return a Promise (implicitly or explicitly), and Promise objects can’t be called as functions. This could cause real issues in your React app, such as memory leaks.


useEffect(async () => {
  const observer = () => {
    // do stuff
  };

  await fetchData();

  observable.subscribe(observer);

  // Memory leak!
  return () => {
    observable.unsubscribe(observer);
  };
}, []);

In this example, because the callback function is async, it doesn’t actually return the defined clean-up function, but rather a Promise object that is resolved with the clean-up function. Hence, this clean-up function is never called, and the observer never unsubscribed from the observable, resulting in a memory leak.

So how can we fix this? How can we use the await operator with an async function in the useEffect() hook?

async/await Solution 1: Call async Function in IIFE

One straightforward way to solve this problem is to await the async function in an immediately invoked function expression (IIFE):


const [books, setBooks] = useState([]);

useEffect(() => {
  (async () => {
    try {
      const books = await fetchBooks();
      setBooks(books);
    } catch (err) {
      console.log('Error occured when fetching books');
    }
  })();
}, []);

As the name suggests, an IIFE is a function that runs as soon as it is defined. They are used to avoid polluting the global namespace and in scenarios where trying an await call could cause problems in the scope containing the IIFE (e.g., in the useEffect() hook).

async/await Solution 2: Call async Function in Named Function

Alternatively, you can await the async function inside a named function:

useEffect(() => {

  // Named function "getBooks"
  async function getBooks() {
    try {
      const books = await fetchBooks();
      setBooks(books);
    } catch (err) {
      console.log('Error occured when fetching books');
    }
  }

  // Call named function
  getBooks();
}, []);

Remember the example using the observable pattern? Here’s how we can use a named async function to prevent the memory leak that occurred:

// ✅ Callback is not async
useEffect(() => {
  const observer = () => {
    // do stuff
  };

  // Named function "fetchDataAndSubscribe"
  async function fetchDataAndSubscribe() {
    await fetchData();
    observable.subscribe(observer);
  }

  fetchDataAndSubscribe();

  // ✅ No memory leak
  return () => {
    observable.unsubscribe(observer);
  };
}, []);

async/await Solution 3: Create Custom Hook

We can also create a custom hook that behaves similarly to useEffect() and can accept an async callback without causing any issues.

The custom hook could be defined this way:

export function useEffectAsync(effect, inputs) {
  useEffect(() => {
    return effect();
  }, inputs);
}

And we’ll be able to call it from multiple places in our code like this:

const [books, setBooks] = useState([]);

useEffectAsync(async () => {
  try {
    const books = await fetchBooks();
    setBooks(books);
  } catch (err) {
    console.log('Error occured when fetching books');
  }
});

With these three approaches, we can now easily use the await operator with async functions in the useEffect() hook.

How to Remove an Item from a State Array in React

In this article, we’re going to learn how to easily remove an item from a state array in React.

The Array filter() Method

To remove an item from a state array in React, call the filter() method on the array, specifying a test that every item in the array apart from the one to be removed will pass, then update the state with the result of filter() with setState.

import { useState } from 'react';

export default function App() {
  const initialState = [
    { id: 1, name: 'Banana', amount: 5 },
    { id: 2, name: 'Apple', amount: 6 },
  ];

  const removeSecond = () => {
    setFruits((current) =>
      current.filter((fruit) => fruit.id !== 2)
    );
  };

  const [fruits, setFruits] = useState(initialState);

  return (
    <div style={{ margin: '16px' }}>
      <button onClick={removeSecond}>Remove second</button>
      {fruits.map((fruit) => (
        <div key={fruit.id}>
          <h2>Name: {fruit.name}</h2>
          <h2>Amount: {fruit.amount}</h2>
          <hr />
        </div>
      ))}
    </div>
  );
}
Removing an item from a state array in React.

We remove the fruit object with the id 2 by returning a condition from the filter() callback that is true only for the items in the array that don’t have an id of 2. Doing this excludes the target item from the array returned from filter().

const initialState = [
  { id: 1, name: 'Banana', amount: 5 },
  { id: 2, name: 'Apple', amount: 6 },
];

const secondRemoved = initialState.filter((fruit) => fruit.id !== 2);

// [ { id: 1, name: 'Banana', amount: 5 } ]
console.log(secondRemoved);

Since App here is a functional component, we use the useState() React hook to create the initial state array. The first value useState() returns lets us access the state data. The second value is a function used to update the state (generically called setState). We pass a function to setState (named setFruits here) to ensure that we get the current/latest state.

const removeSecond = () => {
  // "current" contains the latest state array
  setFruits((current) =>
    current.filter((fruit) => fruit.id !== 2)
  );
};

Tip: Always pass a function to setState when the new state is computed from the current state data.

Don’t Modify State Directly in React

Note that trying to remove the item from the array by modifying it directly using a function like splice() will not work:

const removeSecond = () => {
  // Find the index of the object to be removed
  const secondIndex = fruits.findIndex((fruit) => fruit.id === 2);

  // Mutating the array like this will not update the view
  fruits.splice(secondIndex, 1);
};

State is meant to be immutable in React, so we can’t update the array by mutating it. It has to be replaced with a new array returned from filter() for the view to update.

Remove Items from a State Array Based on Multiple Conditions

If you need to remove an item from the state array based on multiple conditions, you can use the logical AND (&&) or logical OR (&&) operator.

Using the Logical OR (||) Operator

Here is an example of using the logical OR (||) operator to remove an item from a state array.

const initialState = [
  { id: 1, name: 'Banana', amount: 5 },
  { id: 2, name: 'Apple', amount: 6 },
  { id: 3, name: 'Orange', amount: 10 },
  { id: 4, name: 'Watermelon', amount: 1 },
];

const [fruits, setFruits] = useState(initialState);

const remove = () => {
  setFruits((current) =>
    current.filter(
      (fruit) =>
        fruit.name === 'Orange' || fruit.name === 'Apple'
    )
  );
};

Combining a set of operands with the || operator will result in true if at least one of the operands evaluates to true. By using this operator with the filter() method, we return a new array containing only the fruit objects with a name equal to 'Orange' or 'Apple'.

Using the Logical AND (&&) Operator

Here is an example of using the logical AND (&&) operator to remove an item from a state array:

const initialState = [
  { id: 1, name: 'Banana', amount: 5 },
  { id: 2, name: 'Apple', amount: 6 },
  { id: 3, name: 'Orange', amount: 10 },
  { id: 4, name: 'Watermelon', amount: 1 },
];

const [fruits, setFruits] = useState(initialState);

const remove = () => {
  setFruits((current) =>
    current.filter(
      (fruit) => fruit.id !== 2 && fruit.id !== 4
    )
  );
};

Combining operands with the && operator will result in true only if all the operands are true.

By combining the filter() method with the && operator, we are able to specify a compound boolean expression that removes the fruit objects with ids of 2 and 4.

Simplifying Compound Boolean Expressions with De Morgan’s Laws

We can use one of De Morgan’s laws to convert the AND condition from our previous example to an OR condition and reduce the number of negations.

const remove = () => {
  setFruits((current) =>
    current.filter(
      (fruit) => !(fruit.id === 2 || fruit.id === 4)
    )
  );
};

This transformation could make the expression easier to read and understand.

How to Quickly Use a Button as a Link in React

To use a button as a link in React, wrap the button in an anchor (<a>) element. Clicking a link button will make the browser navigate to the specified URL.

JavaScript
export default function MyComponent() { return ( <div> <a href="/posts"> <button>Posts</button> </a> </div> ); }

If you’re using React Router, then wrap the button in the Link component instead, to make the browser navigate to the specified route without refreshing the page when the button is clicked.

JavaScript
import { Link } from 'react-router-dom'; export default function MyComponent() { return ( <div> <Link to="/posts"> <button>Posts</button> </Link> </div> ); }

The react-router-dom Link component renders an anchor element, so it works similarly to the first example.

We can also use custom button components as links by wrapping them with an anchor element or Link component. For example:

JavaScript
import { Link } from 'react-router-dom'; function MyCustomButton({ children }) { return <button>{children}</button>; } export default function MyComponent() { return ( <div> <Link to="/posts"> <MyCustomButton>Posts</MyCustomButton> </Link> </div> ); }

When using Material UI, we can specify a link for the Button component using the href prop.

JavaScript
import { Button } from '@mui/material'; export default function MyComponent() { return ( <div> <Button href="/posts">Posts</Button> </div> ); }

To use as a React Router Link, we can use the component prop of the Button.

JavaScript
import { Button } from '@mui/material'; import { Link } from 'react-router-dom'; export default function MyComponent() { return ( <div> <Button component={Link} to="/posts"> Posts </Button> </div> ); }

Other Material UI components like IconButton also have a component prop. Setting this prop is useful when we want the button component to inherit its color from its parent.

In this scenario, if we wrap the component with a Link, it will inherit its color from the Link instead of the intended parent. For example:

JavaScript
import { IconButton, Box, Typography } from '@mui/material'; import { Link } from 'react-router-dom'; import { Photo } from '@mui/icons-material'; export default function MyComponent() { return ( // We want the IconButton to inherit its parent color (white) <Box sx={{ backgroundColor: 'black', color: 'white', padding: 2 }}> <Typography>Lorem Ipsum</Typography> {/* But this wrapping makes it inherit from this Link */} <Link to="/photos"> <IconButton color="inherit"> <Photo /> </IconButton> </Link> </Box> ); }
The IconButton inherits its color from the Link(blue) instead of the Box (white).
The IconButton inherits its color from the Link (blue) instead of the Box (white).

We can fix this issue by setting the component prop to a Link instead of wrapping:

JavaScript
import { IconButton, Box, Typography } from '@mui/material'; import { Link } from 'react-router-dom'; import { Photo } from '@mui/icons-material'; export default function MyComponent() { return ( <Box sx={{ backgroundColor: 'black', color: 'white', padding: 2 }}> <Typography>Lorem Ipsum</Typography> {/* Setting the "component" prop to a "Link" component */} <IconButton component={Link} to="/photos" color="inherit"> <Photo /> </IconButton> </Box> ); }
The IconButton inherits its color from the Box.
The IconButton inherits its color from the Box.

How to Build an Advanced Space Remover Tool With React

In this article, we’re going to learn how to build a web app that will let us easily remove leading and trailing spaces from any text, with the ability to optionally preserve the indentation of the text. We’ll be using the React.js library to build this tool, let’s get started.

Setting up the Project

Let’s begin by creating a new React app using Create React App. We’ll be using Yarn.

yarn create-react-app remove-spaces

We’ll also be using a bit of TypeScript, you can set it up using the instructions here.

Writing the removeSpaces() Function

The core part of the app will be a removeSpaces() function that takes a string as input and returns a new string with the spaces removed. Let’s write this function in a new remove-spaces.ts file.

src/remove-spaces.ts

export default function removeSpaces(params: {
  text: string;
  leading: boolean;
  trailing: boolean;
  preserveIndent: boolean;
}) {
  let regex: RegExp;
  const { text, leading, trailing, preserveIndent } = params;
  let spaceCountPattern: string | undefined;

  let leadingMatch: string;
  if (leading) {
    if (preserveIndent) {
      const firstSpacePattern = new RegExp(String.raw`^(\s*).+?((\r\n)|\n|$)`);
      const firstSpaces = text.match(firstSpacePattern)?.[1];
      const spaceCount = firstSpaces?.length;
      spaceCountPattern = `{0,${spaceCount}}`;
    } else {
      spaceCountPattern = '*';
    }
    leadingMatch = String.raw`\s${spaceCountPattern}`;
  } else {
    leadingMatch = '';
  }

  const trailingMatch = trailing ? String.raw`\s*?` : '';
  regex = new RegExp(String.raw`((()((\r\n)|\n))|(.*?((\r\n)|\n|$)))`, 'g');
  const lines = text.match(regex);
  const lineRegex = new RegExp(
    String.raw`^${leadingMatch}(.*?)${trailingMatch}((\r\n)|\n|$)`,
    'g'
  );

  const result = lines
    ?.map((line) => {
      if (line === '\r\n' || line === '\n') return line;
      return line.replace(lineRegex, '$1$2');
    })
    .join('');
  return result;
}

Apart from the input string, the function accepts options that will allow the user to customize how the spaces are removed.

When leading is true and preserveIndent is false, the leading spaces are removed from the text, apart from the spaces that add indentation.

When leading is true and preserveIndent is false, all the leading spaces are removed from the text.

When trailing is true, all the trailing spaces are removed from the text.

The function creates a regular expression from the combination of these options. It uses the String replace() method to replace each line of the text with captured groups from the regex.

Testing the removeSpaces() function

We can test this function to be sure it works as intended. Let’s install the Jest testing framework to do this.

yarn add --dev jest ts-jest @types/jest

Initialize ts-jest with the following command:

yarn ts-jest config:init

Let’s write some tests for the function in a new remove-spaces.test.ts file:

src/remove-spaces.test.ts

import removeSpaces from './remove-spaces';

const s2 = '  ';
const s4 = '    ';

const text = `${s4}<div>${s4}
${s4}${s2}<p></p>${s4}
${s4}</div>${s4}`;

it('removes leading spaces without preserving indent', () => {
  const expectation = `<div>${s4}
<p></p>${s4}
</div>${s4}`;
  const result = removeSpaces({
    text,
    leading: true,
    trailing: false,
    preserveIndent: false,
  });
  expect(result).toBe(expectation);
});

it('removes leading spaces and preserves indent', () => {
  const expectation = `<div>${s4}
${s2}<p></p>${s4}
</div>${s4}`;
  const result = removeSpaces({
    text,
    leading: true,
    trailing: false,
    preserveIndent: true,
  });
  expect(result).toBe(expectation);
});

it('removes trailing spaces', () => {
  const expectation = `${s4}<div>
${s4}${s2}<p></p>
${s4}</div>`;
  const result = removeSpaces({
    text,
    leading: false,
    trailing: true,
    preserveIndent: false,
  });
  expect(result).toBe(expectation);
});

it('removes leading and trailing spaces', () => {
  const expectation = `<div>
<p></p>
</div>`;
  const result = removeSpaces({
    text,
    leading: true,
    preserveIndent: false,
    trailing: true,
  });
  expect(result).toBe(expectation);
});

The function should pass all these tests if it was written correctly.

Creating the Text Inputs

It’s time for us to start creating the user interface with React. We’ll begin with the text inputs. We’ll create two – one will take will user input, and the other will be readonly and display the output.

We’ll be using the Material UI framework to make the app look great, you can set it up using the instructions here.

src/App.js

import { Box, Typography, TextField } from '@mui/material';
import { useState } from 'react';

function App() {
  const [input, setInput] = useState('');
  const [output, setOutput] = useState('');

  const handleInputChange = (event) => {
    setInput(event.target.value);
  };

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: 2,
        boxSizing: 'border-box',
      }}
    >
      <Box
        sx={{
          display: 'grid',
          gridTemplateColumns: 'repeat(auto-fit, minmax(400px, 1fr))',
          justifyContent: 'stretch',
          marginTop: 2,
          rowGap: '16px',
        }}
      >
        <Box sx={{ flex: 1, marginRight: 1, textAlign: 'left' }}>
          <Typography>Input</Typography>
          <TextField
            sx={{ width: '100%', marginTop: 1, minWidth: '300px' }}
            multiline
            value={input}
            minRows={10}
            inputProps={{
              style: { maxHeight: '300px', overflow: 'auto' },
            }}
            onChange={handleInputChange}
          ></TextField>
        </Box>
        <Box sx={{ flex: 1, marginLeft: 1, textAlign: 'right' }}>
          <Typography>Output</Typography>
          <TextField
            sx={{
              width: '100%',
              marginTop: 1,
              minWidth: '300px',
            }}
            multiline
            value={output}
            readOnly
            minRows={10}
            inputProps={{
              style: { maxHeight: '300px', overflow: 'auto' },
            }}
          ></TextField>
        </Box>
      </Box>
    </Box>
  );
}

export default App;
Creating the text inputs.

Pasting Input from the Clipboard

Let’s create a button that will paste text from the system clipboard to the input text field when clicked.

src/App.js

// ...
import { Box, Typography, TextField, Stack, Button } from '@mui/material';
import { ContentPaste } from '@mui/icons-material';

function App() {
  // ...

  const pasteInput = async () => {
    setInput(await navigator.clipboard.readText());
  };

  const handlePasteInput = async () => {
    await pasteInput();
  };

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: 2,
        boxSizing: 'border-box',
      }}
    >
      <Stack
        direction="row"
        spacing={2}
        justifyContent="center"
        sx={{ flexWrap: 'wrap', marginTop: 2 }}
      >
        <Box>
          <Button
            onClick={handlePasteInput}
            variant="outlined"
            startIcon={<ContentPaste />}
          >
            Paste input
          </Button>
        </Box>
      </Stack>
      {/* ... */}
    </Box>
  );
}

export default App;
Pasting input from the clipboard.

Adding Options

Let’s create the options that will let the user decide how the spaces will be removed from the text. There will be three boolean options, each represented with a checkbox:

  1. Remove leading spaces
  2. Remove trailing spaces
  3. Preserve indent

We’ll pass the options directly to the removeSpaces() function when the user decides to remove the spaces.

import {
  Box,
  Typography,
  TextField,
  Stack,
  Button,
  FormControlLabel,
  Checkbox,
} from '@mui/material';
import { useState } from 'react';
import { ContentPaste } from '@mui/icons-material';

function App() {
  // ...

  const [leading, setLeading] = useState(true);
  const [trailing, setTrailing] = useState(true);
  const [preserveIndent, setPreserveIndent] = useState(true);

  const handleLeadingChange = (event) => {
    setLeading(event.target.checked);
  };

  const handleTrailingChange = (event) => {
    setTrailing(event.target.checked);
  };

  const handlePreserveIndentChange = (event) => {
    setPreserveIndent(event.target.checked);
  };

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: 2,
        boxSizing: 'border-box',
      }}
    >
      <Box sx={{ display: 'flex', justifyContent: 'center' }}>
        <FormControlLabel
          control={
            <Checkbox checked={leading} onChange={handleLeadingChange} />
          }
          label="Remove leading spaces"
        />
        <FormControlLabel
          control={
            <Checkbox
              checked={preserveIndent}
              onChange={handlePreserveIndentChange}
            />
          }
          label="Preserve indent"
        />
        <FormControlLabel
          control={
            <Checkbox checked={trailing} onChange={handleTrailingChange} />
          }
          label="Remove trailing spaces"
        />
      </Box>
     {/* ... */}
    </Box>
  );
}

export default App;
Adding options.

Removing the Spaces

Now let’s add a button that will cause the spaces to be removed from the input text when clicked.


// ...
import removeSpaces from './remove-spaces';

function App() {
  const handleRemoveSpaces = () => {
    setOutput(removeSpaces({ text: input, leading, trailing, preserveIndent }));
  };

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: 2,
        boxSizing: 'border-box',
      }}
    >
      <Box sx={{ display: 'flex', justifyContent: 'center' }}>
        {/* ... */}
        
        <Box>
          <Button
            onClick={handlePasteInput}
            variant="outlined"
            startIcon={<ContentPaste />}
          >
            Paste input
          </Button>
        </Box>

        {/* Button to remove spaces */}
        <Box>
          <Button
            onClick={handleRemoveSpaces}
            variant="outlined"
            startIcon={<RemoveCircle />}
          >
            Remove spaces
          </Button>
        </Box>
      </Stack>
      {/* ... */}
      </Box>
    </Box>
  );
}

export default App;
Removing the spaces.

Copying Output to Clipboard

Let’s create another button that will copy the text in the output text field to the system clipboard when clicked.


// ...
import { ContentCopy, ContentPaste, RemoveCircle } from '@mui/icons-material';
import removeSpaces from './remove-spaces';

function App() {
  // ...

  const handleCopyOutput = () => {
    navigator.clipboard.writeText(output);
  };

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: 2,
        boxSizing: 'border-box',
      }}
    >
      {/* ... */}
      <Stack
        direction="row"
        spacing={2}
        justifyContent="center"
        sx={{ flexWrap: 'wrap', marginTop: 2 }}
      >
        {/* ... */}
        <Box>
          <Button
            onClick={handleRemoveSpaces}
            variant="outlined"
            startIcon={<RemoveCircle />}
          >
            Remove spaces
          </Button>
        </Box>

        {/* Button to copy output */}        
        <Box>
          <Button
            startIcon={<ContentCopy />}
            onClick={handleCopyOutput}
            variant="outlined"
          >
            Copy output
          </Button>
        </Box>
      </Stack>
          
    </Box>
  );
}

export default App;
Copying output to clipboard.

Combining Paste, Remove, and Copy Actions

It’s quite likely that users will use this tool by performing the following actions in order:

  1. Click the Paste Input button to put the text from the clipboard in the input text field
  2. Click the Remove Spaces button to remove the spaces from the input text and put the result in the output text field
  3. Click the Copy Output to copy the text from the output text field to the clipboard.

To make things easier, we’ll create a button that will let the user perform these three actions at once:

// ...

function App() {
  // ...

  const handlePasteRemoveCopy = async () => {
    const input = await navigator.clipboard.readText();
    const output = removeSpaces({
      text: input,
      leading,
      trailing,
      preserveIndent,
    });
    navigator.clipboard.writeText(output);
    setInput(input);
    setOutput(output);
  };

  return (
    <Box
      sx={{
        height: '100%',
        display: 'flex',
        flexDirection: 'column',
        padding: 2,
        boxSizing: 'border-box',
      }}
    >
      <Box sx={{ display: 'flex', justifyContent: 'center' }}>
        {/* ... */}
        <FormControlLabel
          control={
            <Checkbox checked={trailing} onChange={handleTrailingChange} />
          }
          label="Remove trailing spaces"
        />
      </Box>

      {/* Button to perform past, remove, and copy actions at once */}
      <Box sx={{ display: 'flex', justifyContent: 'center', marginTop: 2 }}>
        <Button onClick={handlePasteRemoveCopy} variant="contained">
          Paste + Remove + Copy
        </Button>
      </Box>

      <Stack
        direction="row"
        spacing={2}
        justifyContent="center"
        sx={{ flexWrap: 'wrap', marginTop: 2 }}
      >
        <Box>
          <Button
            onClick={handlePasteInput}
            variant="outlined"
            startIcon={<ContentPaste />}
          >
            Paste input
          </Button>
        </Box>
        {/* ... */}
      </Stack>
    </Box>
  );
}

export default App;

Our space remover app is complete! We’ve been able to build a handy utility for removing leading and trailing spaces from any text and preserving indentation if necessary.

What Can This Tool Be Used for?

At Coding Beauty, we found this tool useful when creating code snippets displaying a portion of code from an HTML or JSX markup that was indented by some amount. For example, in our Material UI button tutorial, there were times when the file for an example contained markup like this:

The complete source code for an example in the tutorial.
The complete source code for an example in the tutorial.

But we would only want to show the section of the file relevant to the example:

Explaining contained buttons in the Material UI button tutorial.
Explaining contained buttons in the Material UI button tutorial.

This tool helped format the relevant section properly by removing the spaces.

What about String trim()?

We couldn’t use the trim() or trimStart() string methods because then it wouldn’t be possible to preserve the indent of the entire text. These methods can only remove all the leading spaces in a given string.

How to Use the Material UI Button Component

A button is a commonly used component that adds interactivity to a UI. In this article, we’re going to learn how to easily create and customize buttons in Material UI.

The Material UI Button Component

We can use the Button component from Material UI to create buttons. It has a variant prop used to display a text, contained, or outlined button.

App.jsx
import { Box, Button, Stack } from '@mui/material'; export default function App() { return ( <Box> <Stack spacing={2} direction="row" > <Button variant="text">Text</Button> <Button variant="contained">Contained</Button> <Button variant="outlined">Outlined</Button> </Stack> </Box> ); }

Text Button

Text buttons are suitable for actions of low significance in an app, like the closing of a dialog. Setting the variant prop to text displays a text button.

App.jsx
<Button>Primary</Button> <Button disabled>Disabled</Button> <Button href="#text-buttons">Link</Button>
Creating text buttons in Material UI.

Contained Button

Contained buttons indicate the primary and essential actions in our apps. Setting the variant prop to contained displays a contained button.

JavaScript
<Button variant="contained">Contained</Button> <Button variant="contained" disabled> Disabled </Button> <Button variant="contained" href="#contained-buttons"> Link </Button>
Creating contained buttons in Material UI.

Outlined Button

Outlined buttons indicate actions of mid-level significance. They are a lower emphasis alternative to contained buttons and a higher emphasis alternative to text buttons. Setting the variant prop to outlined displays and outlined button.

JavaScript
<Button variant="outlined">Primary</Button> <Button variant="outlined" disabled> Disabled </Button> <Button variant="outlined" href="#outlined-buttons"> Link </Button>
Creating outlined buttons in Material UI.

Disabled Button Elevation

We can prevent a button from being clicked by setting the disableElevation prop to true.

JavaScript
<Button variant="contained" disableElevation > Elevation disabled </Button>
Disabling button elevation.

Handling Button Clicks in Material UI

We can assign a listener function to the onClick prop to perform an action when the button is clicked.

In the following example, we attach a listener that increments a count by one, to display the total number of times the button has been clicked.

JavaScript
import { Box, Button, Typography } from '@mui/material'; import { useState } from 'react'; export default function App() { const [count, setCount] = useState(0); return ( <Box sx={{ margin: 2 }}> <Button onClick={() => { setCount(count + 1); }} variant="contained" > Click me </Button> <Typography sx={{ marginTop: 1 }}>Count: {count}</Typography> </Box> ); }
Handling button clicks in Material UI.

Material UI Button Colors

We can use the color prop to apply a color from the theme palette.

JavaScript
<Button color="secondary">Secondary</Button> <Button variant="contained" color="success"> Success </Button> <Button variant="outlined" color="error"> Error </Button>
Applying color to buttons.

Custom Colors

The color prop only allows values from the theme palette. To apply a color not available in the theme, we can use custom CSS and the sx prop.

JavaScript
import { Stack, Button } from '@mui/material'; import { green } from '@mui/material/colors'; export default function App() { return ( <Stack spacing={2} direction="row" > <Button sx={{ backgroundColor: green[500], '&:hover': { backgroundColor: green[700] }, }} variant="contained" > Primary </Button> <Button sx={{ color: green[500], borderColor: green[500], '&:hover': { color: green[500], borderColor: green[500] }, }} variant="outlined" > Secondary </Button> </Stack> ); }

Button Sizes

The size prop of the Button component allows us to create buttons of different sizes.

JavaScript
import { Box, Button } from '@mui/material'; export default function App() { return ( <Box> <Box sx={{ '& button': { m: 1 } }}> <div> <Button size="small">Small</Button> <Button size="medium">Medium</Button> <Button size="large">Large</Button> </div> <div> <Button variant="outlined" size="small" > Small </Button> <Button variant="outlined" size="medium" > Medium </Button> <Button variant="outlined" size="large" > Large </Button> </div> <div> <Button variant="contained" size="small" > Small </Button> <Button variant="contained" size="medium" > Medium </Button> <Button variant="contained" size="large" > Large </Button> </div> </Box> </Box> ); }
Creating buttons of different sizes in Material UI.

Icon and Label Buttons

Including an icon in a button can make clearer to the user the action the button performs. Assigning the icon component to the startIcon or endIcon prop aligns the icon to the left or right of the label respectively.

JavaScript
import { Button, Stack } from '@mui/material'; import { Settings as SettingsIcon, PlayArrow as PlayArrowIcon, } from '@mui/icons-material'; export default function App() { return ( <Stack spacing={2} direction="row" > <Button variant="contained" startIcon={<PlayArrowIcon />} > Play </Button> <Button variant="outlined" endIcon={<SettingsIcon />} > Settings </Button> </Stack> ); }
Creating a button with an icon and a label.

Icon Buttons in Material UI

Icon buttons can help save screen space and ease user recognition. We can use the IconButton component from Material UI to create them.

JavaScript
import { IconButton, Stack } from '@mui/material'; import { Settings, Delete, Info, ContentCopy } from '@mui/icons-material'; export default function App() { return ( <Stack spacing={2} direction="row" > <IconButton> <Settings /> </IconButton> <IconButton color="primary"> <Delete /> </IconButton> <IconButton color="secondary"> <Info /> </IconButton> <IconButton disabled color="primary" > <ContentCopy /> </IconButton> </Stack> ); }
Creating icon buttons in Material UI.

Icon Button Sizes

Like Button, IconButton also comes with a size prop for customizing its size.

JavaScript
<IconButton size="small"> <Settings fontSize="small" /> </IconButton> <IconButton size="medium"> <Settings fontSize="medium" /> </IconButton> <IconButton size="large"> <Settings fontSize="large" /> </IconButton>
Create icon button components of different sizes.

Icon Button Colors

The color prop lets us apply a color from the theme palette to an IconButton.

JavaScript
import { IconButton, Stack } from '@mui/material'; import { Settings as SettingsIcon } from '@mui/icons-material'; export default function App() { return ( <Stack spacing={1} direction="row" > <IconButton color="primary"> <SettingsIcon /> </IconButton> <IconButton color="secondary"> <SettingsIcon /> </IconButton> <IconButton color="success"> <SettingsIcon /> </IconButton> <IconButton color="error"> <SettingsIcon /> </IconButton> <IconButton color="warning"> <SettingsIcon /> </IconButton> </Stack> ); }
Customizing icon button colors.

Loading Buttons in Material UI

A loading button can indicate an ongoing operation and temporarily disable interaction. We can create one with the LoadingButton component.

JavaScript
import { Stack } from '@mui/material'; import { LoadingButton } from '@mui/lab'; import { Save as SaveIcon } from '@mui/icons-material'; export default function App() { return ( <Stack spacing={2} direction="row" > <LoadingButton loading variant="contained" > Play </LoadingButton> <LoadingButton loading loadingIndicator="Loading..." variant="outlined" > Send message </LoadingButton> <LoadingButton loading loadingPosition="start" startIcon={<SaveIcon />} variant="outlined" > Save </LoadingButton> </Stack> ); }
Creating a loading button in Material UI.