React Tips — Testing, Redirects, and Markdown

John Au-Yeung - Jan 21 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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.

Pass Props with Redirect Component with React Router

We can pass props with React Router’s Redirect component by passing in the state value.

For instance, we can write:

<Redirect
  to={{
    pathname: '/order',
    state: { id: '123' }
  }}
/>
Enter fullscreen mode Exit fullscreen mode

We pass in the pathname for the URL path.

And the state has the state we want to pass to the component.

And then we can write:

this.props.location.state.id
Enter fullscreen mode Exit fullscreen mode

to get the id in the component.

Distinguish Left and Right Click Events with React

We can distinguish between left and right-click by checking the type property of the event object.

For instance, if we have:

return <p onClick={this.handleClick} onContextMenu={this.handleClick}>click me</p>
Enter fullscreen mode Exit fullscreen mode

Then we can write:

handleClick(e) {
  if (e.type === 'click') {
    console.log('Left click');
  } else if (e.type === 'contextmenu') {
    console.log('Right click');
  }
}
Enter fullscreen mode Exit fullscreen mode

This is detecting a synthetic event.

We can also detect left and right click with nativeEvent :

handleClick(e) {
  if (e.nativeEvent.which === 1) {
    console.log('Left click');
  } else if (e.nativeEvent.which === 3) {
    console.log('Right click');
  }
}
Enter fullscreen mode Exit fullscreen mode

The which property has the click type.

1 is left click and 3 is for right-click.

Using Jest to Spy on Method Call in componentDidMount

We can use the spyOn method to check which component method is called.

for instance, we can write:

const spy = jest.spyOn(Component.prototype, 'someMethod');
const wrapper = mount(<Component {...props} />);
wrapper.instance().someMethod();
expect(spy).toHaveBeenCalled();
Enter fullscreen mode Exit fullscreen mode

Component is the component we’re testing.

someMethod is the method we’re spying.

We mount the component and get the instance with the instance method.

someMethod is the method we called.

Then spy should be called.

And then we clear our spies with:

afterEach(() => {
  spy.mockClear()
})
Enter fullscreen mode Exit fullscreen mode

after each test.

How to Capture Only Parent’s Click Event and not Children

We should call preventDefault to capture only the parent component’s click event and not the children’s.

For instance, we can write:

onParentClick(event) {
  event.preventDefault();
  console.log(event.currentTarget);
}
Enter fullscreen mode Exit fullscreen mode

How to Render Markdown from a React Component

We can render markdown with the react-markdown library.

For instance, we can write:

import React from 'react'
import Markdown from 'react-markdown'

const code = "# header";

React.render(
  <Markdown source={code} />,
  document.getElementById('root')
);
Enter fullscreen mode Exit fullscreen mode

We get the Markdown component form the package.

And then we pass in the code to the source prop to render it.

Also, we can convert it to HTML and then render than with dangerousSetInnerHTML with the marked library.

For instance, we can write:

import React from 'react';
import marked from 'marked';

class Markdown extends React.Component {
  constructor(props) {
    super(props);

    marked.setOptions({
      gfm: true,
      tables: true,
      breaks: false,
      pedantic: false,
      sanitize: true,
      smartLists: true,
      smartypants: false
    });
  }
  render() {
    const { text } = this.props,
    html = marked(text || '');

    return (
      <div>
        <div dangerouslySetInnerHTML={{__html: html}} />
      </div>
    );
  }
}

Markdown.propTypes = {
  text: React.PropTypes.string.isRequired
};

Markdown.defaultProps = {
  text: ''
};
Enter fullscreen mode Exit fullscreen mode

We set the options with the setOptions method.

gfm means we render Github flavored Markdown.

tables means we render tables.

breaks mean we render line breaks with br.

pedantic means we conform to the original Markdown spec and don’t fix their bugs or behavior.

sanitize we sanitize the HTML.

smartLists uses the smartlist behavior of the Markdown spec.

smartypants means using smart typographic punctuation for things like quotes and slashes.

Testing with Jest Using Date Objects Produce Different Snapshots in Different Timezones

We can set the current time to be a constant time in Jest.

For instance, we can write:

Date.now = jest.fn(() => new Date(Date.UTC(2020, 7, 9, 8)).valueOf())
Enter fullscreen mode Exit fullscreen mode

Then we can set the timezone when we run our tests.

In Mac and Linux, we add:

"test": "TZ=America/Los_Angeles react-scripts test --env=jsdom",
Enter fullscreen mode Exit fullscreen mode

And in Windows, we add:

"test": "set TZ=America/Los_Angeles && react-scripts test --env=jsdom",
Enter fullscreen mode Exit fullscreen mode

to package.json ‘s scripts section.

Conclusion

We can pass states to the Redirect component.

Also, we can set the time zone for the and date for Jest tests.

We can also spy on function calls with them.

We can also capture left and right clicks and clicks from parent elements only.

There are various ways to render Markdown in our React component.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .