Categories
React Tips

React Tips — Dispatch and Navigate, useCallback, and Cleanup

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.

React.useState does not Reload State from Props

React.useState doesn’t reload state from props.

It can only set the initial state.

If we need to update the state as props change, then we need to use the useEffect hook.

For instance, we can write:

function Avatar({ username }) {
  const [name, setName] = React.useState(username);

  React.useEffect(() => {
    setName(name);
  }, [username])

  return <img src={`${name}.png`}/>
}

We get the username prop .

And we set it as the initial value of the name state with useState .

Then we use the useEffect hook to watch for changes in the name value.

We watch it for changes, then call setName to set the name with the latest value of username as the name ‘s new value.

Then we can use name in the JSX we render.

Use for useCallback

We can use useCallback to cache the callback so that we don’t call a create a new instance of the callback function on every render.

For instance, instead of writing:

function Foo() {
  const handleClick = () => {
    console.log('clicked');
  }
  <button onClick={handleClick}>click me</button>;
}

We write:

function Foo() {
  const memoizedHandleClick = useCallback(
    () => console.log('clicked'), [],
  );

  return <Button onClick={memoizedHandleClick}>Click Me</Button>;
}

The useCallback hook caches the click callback so that the same instance is used on every render instead of creating a new one.

Detect a React Component vs. a React Element

We can check if an object is a function component by checking that it’s a function and that it contains the 'return React.createElement' code.

For instance, we can write:

const isFunctionComponent = (component) => {
  return (
    typeof component === 'function' &&
    String(component).includes('return React.createElement')
  )
}

To check for a class component we can check for type 'function' .

And we can check for the isReactComponent property in the component’s prototype .

For example, we can write:

const isClassComponent = (component) => {
  return (
    typeof component === 'function' &&
    !!component.prototype.isReactComponent
  )
}

To check if a variable is a valid element, we can use the React.isValidElement method to do that.

For example, we can write:

const isElement = (element) => {
  return React.isValidElement(element);
}

React Hooks useEffect() Cleanup When Component Unmounts

We can return a function in the useEffect callback to return a function that runs our clean up code.

For example, we can write:

const { useState, useEffect } = React;

const ForExample = () => {
  const [name, setName] = useState("");
  const [username, setUsername] = useState("");

  useEffect(
    () => {
      console.log("do something");
    },
    [username]
  );

  useEffect(() => {
    return () => {
      console.log("cleaned up");
    };
  }, []);

  const handleName = e => {
    const { value } = e.target;
    setName(value);
  };

  const handleUsername = e => {
    const { value } = e.target;
    setUsername(value);
  };

  return (
    <div>
      <div>
        <input value={name} onChange={handleName} />
        <input value={username} onChange={handleUsername} />
      </div>
    </div>
  );
};

We have our change event handlers.

And we have our useEffect calls.

They all have their own callbacks.

The first one watches for changes in the username function.

In the 2nd one, the callback returns a function that runs code when the component unmounts.

React Router Redirect after Redux Action

We can redirect after a Redux action is committed.

To do that, we install the history package.

We install it by running:

npm install --save history

Then we can create a function like:

import { createBrowserHistory } from 'history';

const browserHistory = createBrowserHistory();

const actionName = () => (dispatch) => {
  axios
    .post('url', { body })
    .then(response => {
       dispatch({
         type: ACTION_TYPE_NAME,
         payload: payload
       });
       browserHistory.push('/foo');
    })
    .catch(err => {
      // Process error code
    });
  });
};

We make a POST request with Axios.

Then in the then callback, we call dispatch to dispatch our actions.

And then we call browserHistory.push to navigate.

We called createBrowserHistory to get the browserHistory object.

Conclusion

We use the useEffect hook to update our values.

It can also be used to run clean up code when a component unmounts.

If we need to navigate to another route after a Redux action is done, we can use the browserHistory.push method to do that after we dispatched our action.

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 *