Categories
React

How to Handle an Input with React Hooks?

Handling input values is something that we’ve to do often in our React components.

In this article, we’ll look at how to handle inputs with React hooks.

Using the useState Hook

To make an input’s value usable in our React component, we’ve to set the input value as a state’s value.

To do this, we can use the useState hook.

For instance, we can write:

import React from "react";

export default function App() {
  const [inputValue, setInputValue] = React.useState("");

  const onChangeHandler = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <div>
      <input
        type="text"
        name="name"
        onChange={onChangeHandler}
        value={inputValue}
      />
      <p>{inputValue}</p>
    </div>
  );
}

We call the useState hook to return an array with the inputValue state and the setInputValue function to set the inputValue state.

Then we define the onChangeHandler function with the event parameter that calls the setInputValue to set the inputValue state.

event.target.value has the input value.

And then we add an input element and pass in the onChangeHandler event handler and the inputValue state into the onChange and value props respectively.

Then we show the inputValue .

We set the value prop to inputValue so we’ll see what we typed into the input.

If we use inputs often, we may also want to put the input logic in a hook:

import React, { useState } from "react";

const useInput = ({ type }) => {
  const [value, setValue] = useState("");
  const input = (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}
      type={type}
    />
  );
  return [value, input];
};

export default function App() {
  const [username, userInput] = useInput({ type: "text" });

  return (
    <div>
      {userInput}
      <p>{username}</p>
    </div>
  );
}

We create the useInput hook that takes an object with thew type property so we can set the input type.

Then we call useInput in App to use it.

We put the userInput component in the div and the username , which has the input value.

The hook has the same logic as we have before.

So we see the inputted value rendered when we type into the input.

Conclusion

We can handle input values by calling a state setter function with the input value so we can use the input value in our component.

Categories
React

How to use Throttle or Debounce with React Hook?

Sometimes, we may want to delay or throttle the number of times a piece of code is run in our React component.

In this article, we’ll look at how to throttle or denounce code with React hooks.

Using the Lodash Throttle Function

Lodash comes with the throttle function to let us limit a function to run once in a given time interval.

For instance, we can write:

import React, { useEffect, useRef, useState } from "react";
import { throttle } from "lodash";

export default function App() {
  const [value, setValue] = useState(0);
  const throttled = useRef(throttle((newValue) => console.log(newValue), 1000));

  useEffect(() => throttled.current(value), [value]);

  return <button onClick={() => setValue(value + 1)}>{value}</button>;
}

We call throttle with the function that we want to run and the time interval in milliseconds.

Therefore, the function runs once every 1000 milliseconds at the maximum.

We put th throttled function in the useRef hook to set the throttled function as the value of throttled.current .

This will cache the function between re-renders so it won’t be recreated on every render.

We then call the function we created in the useEffect callback.

So when we click on the button, we see the throttled function runs every 1-second max.

Use the useCallback Hook to Store the Throttled Function

We can replace the ref with the useCallback hook.

For instance, we can write:

import React, { useCallback, useEffect, useState } from "react";
import { throttle } from "lodash";

export default function App() {
  const [value, setValue] = useState(0);
  const throttled = useCallback(
    throttle((newValue) => console.log(newValue), 1000),
    []
  );

  useEffect(() => throttled(value), [value]);

  return <button onClick={() => setValue(value + 1)}>{value}</button>;
}

We just pass in our throttled function into the useCallback hook to cache the function between re-renders.

And we get the same result as before.

Debouncing Functions

Debouncing functions means we call a function after a delay.

To do this, we can create our own hook by writing:

import React, { useCallback, useEffect, useState } from "react";

const useDebouncedEffect = (effect, delay, deps) => {
  const callback = useCallback(effect, deps);

  useEffect(() => {
    const handler = setTimeout(() => {
      callback();
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [callback, delay]);
};

export default function App() {
  const [value, setValue] = useState(0);

  useDebouncedEffect(() => console.log(value), 1000, [value]);

  return <button onClick={() => setValue(value + 1)}>{value}</button>;
}

We create the useDebouncedEffect hook by calling setTimeout in the useEffect callback.

The callback we call is passed in from the effect function.

We call useCallback to cache the effect function so that it won’t be recreated every time the component is rendered.

deps has the dependencies we want to watch. When the value changes, useCallback will recreate the function.

setTimeout returns a timer object so we can use that to clear it when the component unmounts.

When we unmount the component, we call clearTimeout to clear the timer.

In App , we use the useDebouncedEffect hook with a callback that we want to run after a delay.

Now when we click on the button, we wait 1000 milliseconds until the callback is run.

Conclusion

We can add throttle and denounce easily with React.

Categories
React

How to Make the React useEffect Hook Not Run on Initial Render?

Sometimes, we may want to make our useEffect callback not run on initial render.

In this article, we’ll look at how to make the React useEffect callback not run on initial render.

Store the Render State in a Ref

We can create a hook to check whether the first render is done before running the code we want.

To do this, we write:

import React, { useEffect, useRef, useState } from "react";

const useDidMountEffect = (func, deps) => {
  const didMount = useRef(false);

  useEffect(() => {
    if (didMount.current) {
      func();
    } else {
      didMount.current = true;
    }
  }, deps);
};

export default function App() {
  const [count, setCount] = useState(0);

  useDidMountEffect(() => {
    console.log("second render");
  });

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <p>{count}</p>
    </div>
  );
}

We create the useDidMountEffect hook to track whether the first render is done.

We do this with the didMount ref.

We have the useEffect hook that runs on when the deps array is changed.

If it’s the first render, we set didMount.current to true .

Otherwise, we run the func function.

In App , we have the count state which is updated when we click on the increment button.

We also pass a callback to the useDidMountEffect hook which we created.

When we click on the increment button, we see 'second render' logged after the first render.

Conclusion

We can make the React useEffect callback not run on the first render by creating a ref that keeps track of whether the first render is done.

Then we can check the ref’s value to see when the first render is done and run the function we want when the first render is done.

Categories
React

What is the Equivalent of the componentDidMount Method in a React Function/Hooks Component?

When we’re creating React components with classes, we run our code that loads when the component mounts in the componentDidMount hook.

However, with React components, this isn’t available.

In this article, we’ll look at how to produce the same result with the componentDidMount hook within React function components.

The useEffect Hook

To run code only when the component mounts, we can use the useEffect hook.

If we pass in an empty array as the 2nd argument, then the useEffect callback in the 1st argument will only run when the component mounts.

For instance, we can write:

import React, { useEffect } from "react";

export default function App() {
  useEffect(() => {
    console.log("mounted");
  }, []);

  return <div className="App"></div>;
}

Now we should only see the 'mounted' string logged when we mount the component.

React Hooks Equivalent of componentDidUpdate

The equivalent of the componentDidUpdate lifecycle method is also the useEffect hook.

componentDidUpdate runs when a state or prop changes values.

We can do the same thing with useEffect by passing in the state or prop values we want to watch into the array we pass into the 2nd argument of useEffect .

For instance, we can write:

import React, { useEffect, useState } from "react";

const Count = ({ count }) => {
  useEffect(() => {
    console.log(count);
  }, [count]);

  return <p>{count}</p>;
};

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <Count count={count} />
    </div>
  );
}

to watch the count prop for updates with the useEffect hook in the Count component.

To watch a state, we can write:

import React, { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(count);
  }, [count]);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <p>{count}</p>
    </div>
  );
}

We watch the count state the same way with the useEffect hook.

React Hooks Equivalent of componentWillUnmount

The componentWillUnmount lifecycle method in a React class component lets us run code when we unmount a component.

We can do the same thing with the useEffect hook again.

We just have to return a function in the useEffect callback to do this.

The function we return will run when the component unmounts.

For instance, we can write:

import React, { useEffect } from "react";

export default function App() {
  useEffect(() => {
    console.log("mounted");
    return () => {
      console.log("unmounted");
    };
  }, []);

  return <div className="App"></div>;
}

to return a function in th useEffect callback.

Then we should see 'unmounted' when we unmount the App component.

Conclusion

We can use the useEffect hook in React function components to do the things that lifecycle methods can do in class components.

Categories
React

How to Trigger a Component to Re-render with Hooks in React?

Sometimes, we may want to trigger a component to re-render in a component created with React hooks.

In this article, we’ll look at ways we can trigger a component to re-render in a React component created with hooks.

Update a Prop or State

A component will re-render if a prop or state value changes.

Therefore, we can just trigger a re-rendering of a component when we update a prop or state value.

To update a state, we call a state setter function.

For instance, we can write:

import React, { useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <p>{count}</p>
    </div>
  );
}

to add a button that calls setCount to update the count state.

We know the App component re-rendered since the latest value of count is displayed below it when we click the increment button.

Likewise, we can update a prop value to trigger a re-render of a component.

For instance, we can write:

import React, { useState } from "react";

const Count = ({ count }) => <p>{count}</p>;

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <Count count={count} />
    </div>
  );
}

We have the Count component that takes the count prop and renders the count value.

To make the Count component re-render, we update the value of the count prop by updating the value of the count state in App .

This part is the same as the previous example.

And we know Count re-rendered since we see the latest value of count rendered again.

Forcing a Re-rendering of a React Component

Sometimes, we may want to force a re-rendering of a React component when something external to a component is updated.

To do this, we can create our own hook.

For instance, we can write:

import React, { useCallback, useState } from "react";

let count = 0;

setInterval(() => {
  count++;
}, 1000);

const useForceUpdate = () => {
  const [, setTick] = useState(0);
  const update = useCallback(() => {
    setTick((tick) => tick + 1);
  }, []);
  return update;
};

export default function App() {
  const update = useForceUpdate();

  return (
    <div className="App">
      <button onClick={() => update()}>update</button>
      <p>{count}</p>
    </div>
  );
}

We have a setInterval callback that sets the count variable’s value.

And we create the useForceUpdate hook that updates a state with the setTick function.

setTick is called in the update function which we return so we can use it in our component code.

In App , we call useForceUpdate to and assigned the returned value to the update variable.

Then in the button we call update when we click on it.

Therefore, when we click on it, we see the latest value of count displayed.

Conclusion

There are several ways to trigger a re-rendering of a React component with React hooks.