Categories
React Tips

React Tips — Back Button, Stop Event Bubbling, Merging States

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.

Prevent Event Trigger on Parent From Child

We can prevent an event from bubbling from child to parent by calling the stopPropagation method.

For instance, we can write:

class App extends Component {
  constructor(){
    super();
  }

  handleParentClick(e) {
    console.log('parent clicked');
  },

  handleChildClick(e) {
    e.stopPropagation();
    console.log('child clicked');
  },

  render() {
    return (
      <div>
        <p onClick={this.handleParentClick}>
          <span onClick={this.handleChildClick}>Click</span>
        </p>
      </div>
    );
  }
}

We created a component that has a parent and child element.

The span has the handleChildClick handler attached to it.

Since we called e.stopPropagation , we won’t get the child’s event bubbling to the parent.

We also have a handleParentClick handler that’s attached to the p element.

Download a File in React

We can create a file download link in a few ways.

One way is to use the React Router’s Link component by writing:

<Link to="/files/file.pdf" target="_blank" download>Download</Link>

We can also create a link and click on it to trigger the download.

For instance, we can write:

const link = document.createElement('a');
link.href = `file.pdf`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

We can also use an anchor tag by writing:

<a href={uploadedFileLink} target="_blank" rel="noopener noreferrer">
   download file
</a>

We have the rel=”noopener noreferrer” attribute so that we can prevent security issues with cross-origin destinations.

This attribute will prevent outside domains from accessing the current website.

Intercept or Handle the Browser’s Back Button in React Router

We can listen to back button actions by running the setRouteLeaveHook event for back button actions.

For instance, we can write:

import {Component} from 'react';
import {withRouter} from 'react-router';

class App extends Component {
  componentDidMount() {
    this.props.router.setRouteLeaveHook(this.props.route, this.onLeave);
  }

  onLeave(nextState) {
    if (nextState.action === 'POP') {
      //...
    }
  }

  //...
}

export default withRouter(App);

We call withRouter to inject the router object, which has the setRouteLeaveHook method to let us listen for changes to this.props.route .

Then we created our own onLeave methods which we pass in as the 2nd argument.

It takes the nextState object which has the action which we can check for.

If it’s 'POP' , then the back button is pressed.

With a function component, we can listen to the history object for changes.

history has the action property which returns the action that’s being done.

If it’s 'POP' , then we know that the user pressed the back button.

For instance, we can write;

import { useHistory } from 'react-router-dom'

const App = () => {
  const { history } = useRouter();

  useEffect(() => {
    return () => {
      if (history.action === "POP") {
        //...
      }
    };
  }, [history])

  //...
}

We put it in the function we return in the useEffect callback so that we can check when the component is being unmounted.

There’s also the history.listen method that lets us listen for changes to the history.

For instance, we can write:

import { useHistory } from 'react-router-dom'

const App = () => {
  const history = useHistory();

  useEffect(() => {
    return history.listen(location => {
      if (history.action === 'POP') {
        //...
      }
    })
  }, [])

  //...
}

We can listen to the 'POP' action as we do in the previous examples.

Updating and Merging State Object Using React useState() Hook

To update and merge state objects with useState , we can pass in a callback to the state change function.

It takes the value of the previous stage as the parameter and returns the new state value that we want.

For instance, we can write:

setState(prevState => {
  return { ...prevState, ...newValues };
});

We used the spread operator to spread all the properties from the new and old state objects.

Also, we can use Object.assign to do the same thing.

For example, we can write:

setState(prevState => {
  return Object.assign({}, prevState, newValues);
});

which does the same thing.

Or we can just merge it in if we don’t really care about the current state value.

We can just write:

setState({
  ...state,
  foo: 'bar'
});

There are no guarantees about state ‘s value.

Conclusion

There are many ways to merge old states with new states.

We can call stopPropagation to stop propagation events.

There are many ways to watch for back button presses.

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 *