Categories
React Tips

React Tips — useEffect, Load Data, and refs

Spread the love

React is a popular library for creating web apps and mobile apps.

In this article, we’ll look at some tips for writing better React apps.

Updating State not When Using React State Hook within setInterval

We can set the state within the setInterval callback to update the state when it’s run.

For instance, we can write:

const App = () => {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    const timer = window.setInterval(() => {
      setCount(count => count + 1)
    }, 1000);

    return () => {
      window.clearInterval(timer);
    };
  }, []);

  return (
    <div>{count}</div>
  );
}

We add the setInterval function into the useEffect callback.

We call setCount inside the callback by passing in a callback that returns the count + 1 .

count is the state that we want to set.

We return a function to clear the timer with clearInterval so that it’s cleared when the component unmounts.

The empty array will ensure that the useEffect callback is run when the component mounts.

Reduce State Updater Calls in Function Component

To reduce state updater calls in a function component, we can use one state to store an object.

And we can use the state update function to update the object instead of using multiple state updater functions to update individual values.

For instance, we can write:

const {useState, useEffect} = React;

function App() {
  const [userRequest, setUserRequest] = useState({
    loading: false,
    user: null,
  });

  useEffect(() => {
    setUserRequest({ loading: true });
    fetch('https://randomuser.me/api/')
      .then(res => res.json())
      .then(data => {
        const [user] = data.results;
        setUserRequest({
          loading: false,
          user
        });
      });
  }, []);

  const { loading, user } = userRequest;

  return (
    <div>
      {loading && 'Loading...'}
      {user && user.name.first}
    </div>
  );
}

We have the setUserTequest function that updates a state that’s stored as an object.

It has the loading and user properties.

loading is the boolean to indicate loading.

user has the user data.

We set the loading property with setUserRequest when the useEffect callback first runs.

And in the then callback, we called our API.

And then we get the data and render it afterward.

The empty array ensures that the callback only loads when the component mounts.

Set State Inside a useEffect Hook

We can set state inside the useEffect hook by merging the values of the existing state with the new values and returning that as the state in the state updater function.

For instance, we write:

useEffect(() => {
  setState(state => ({ ...state, foo: props.foo }));
}, [props.foo]);

useEffect(() => {
  setState(state => ({ ...state, bar: props.bar }));
}, [props.bar]);

We watch the props properties by passing them into the array.

Then we merge the items into the state object that we return in the callback.

componentDidMount Called Before ref Callback

refs are set before the componentDidMount and componentDidUpdate hooks are called.

For instance, if we have:

class App extends Component {
  componentDidMount() {
    //...
  }

  componentDidUpdate() {
    //...
  }

  render() {
    return <div ref={(el) => {this.divRef = el}} />;
  }
}

We set the ref in render and we’re guaranteed that we can use it anywhere else in the component since it’s set before any of the lifecycle hooks are run.

React Async Rendering of Components

Components are always re-rendered when we update the state, so we can just make sure that we call setState to update the states.

For instance, we can write:

import React from 'react';

export default class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      data: null
    }
  }

  componentDidMount(){
    const endpoint = 'https://randomuser.me/api/';
    fetch(endpoint)
      .then((resp) => resp.json())
      .then((response) => {
        const [data] = response.results;
        setState({ data });
      });
  }

  render(){
    return (<div>
      {this.state.data === null ?
        <div>Loading</div>:
        <div>{this.state.data.name}</div>
      }
     </div>)};
}

We call setState when we got our data in the compoenentDidMount method.

Now we get the data displayed in the code when we have the data set as the value of the data state.

Otherwise, we see the Loading message.

Conclusion

We can load data with the componentDidMount hook.

Also, we can watch for value changes in the useEffect hook.

refs are assigned before class component lifecycle hooks.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *