Categories
React Tips

React Tips — Mock React-Redux, Internationalization, and Connect Redux with React

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.

How to Unit Test React-Redux Connected Components

We can test a React-Redux connected component by mocking the connect function and Provider component with our own code.

For instance, we can write:

jest.mock('react-redux', () => {
  return {
    connect: (mapStateToProps, mapDispatchToProps) => (Component) => ({
      mapStateToProps,
      mapDispatchToProps,
      Component
    }),
    Provider: ({ children }) => children
  }
})

We create a mock version of React Redyx by creating a mock module with the connect function.

It takes a mapStateToProps and mapDispatchToProps methods like the real thing.

And it returns a function that takes a React component and returns an object with all the parameters in it.

To mock the Provider we just return the children from the prop.

This can be used inline within a file.

To put the mock in a separate file, we can write:

module.exports = {
  connect: (mapStateToProps, mapDispatchToProps) => (Component) => ({
    mapStateToProps,
    mapDispatchToProps,
    Component,
  }),
  Provider: ({children}) => children
};

in __mocks__/react-redux.js .

The __mocks__ folder should be in the root folder.

Unless we call jest.unmock(‘react-redux’)) the mock will be used.

PropTypes in Stateless Functional Component

We can set prop types in stateless function components.

For instance, we can write:

import React from 'react';
import PropTypes from 'prop-types';

function List(props) {
  const todos = props.todos.map((todo, index) => (<p key={index}>{todo}</p>));
  return (<div>{todos}</div>);
}

List.propTypes = {
  todos: PropTypes.array.isRequired,
};

We assign the propTypes property with an object with the prop types.

And then we use the PropTypes object to specify the type.

How to Maintain State After a Page Refresh in React

To maintain state after a page refresh in React, we can store the state we want to keep in local storage.

For instance, we can write:

constructor() {
  const selectedOption = localStorage.getItem('selectedOption');
  this.state = {
    selectedOption
  };
}

setSelectedOption(option) {
  localStorage.setItem('selectedOption', option);
  this.setState({ selectedOption: option });
}

We have the constructor that gets the saved state from local storage with getItem .

Then in another method, we set the option in the local storage and the state.

Use Redux’s Store with React

To access a Redux store with a React component, we can use the connect function.

For instance, we can write:

import { connect } from 'react-redux'
import { setVisibilityFilter } from '../actions'
import Link from '../components/Link'

const mapStateToProps = (state, ownProps) => {
  return {
    active: ownProps.name === state.name
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onClick: () => {
      dispatch(setName(ownProps.name))
    }
  }
}

const NameLink = connect(
  mapStateToProps,
  mapDispatchToProps
)(Link)

export default NameLink

With our mapStateToProps function, we return the active Redux state as a prop for the Link component.

Also, we have the mapDispatchToProps function to let us create a function that calls dispatch dispatch an action to our Redux store.

Then we can pass them all to the connect function, which returns a higher-order component.

Then we can pass in our Link component to return a new component to add the state and dispatch functions as props.

How to use FormattedMessage in input placeholder with React-Intl

To pass in a placeholder that’s translated with the react-intl, we can call the formatNwessage method with an object to interpolate the placeholders.

For instance, we can write:

import React from 'react';
import { injectIntl, intlShape } from 'react-intl';

const Input = ({ intl }) => {
  const placeholder = intl.formatMessage({ id: 'messageId' });
  return(
     <input placeholder={placeholder} />
  );
}

Input.propTypes = {
  intl: intlShape.isRequired
}

export default injectIntl(Input);

We use the injectIntl higher-order component to inject the intl prop to our component.

It has the formatMessage method that we can interpolate our placeholders with.

It returns a string so that we can use it in in our placeholder prop.

With function components, we can use the useIntl hook to do the same thing.

For instance, we can write:

import React from 'react';
import { useIntl } from 'react-intl';

const Input = () => {
  const intl = useIntl();
  const placeholder = intl.formatMessage({ id: 'messageId' });
  return(
     <input placeholder={placeholder} />
  );
};

export default Input;

We use the useIntl hook to get the intl object.

Then we can call formatMessage on it to interpolate our string.

Conclusion

We can use the react-intl for internationalization.

Also, the react-redux module can be mocked in our tests.

Props types can be set in function components.

We can save our state to local storage to make it persist during refresh.

Categories
React Tips

React Tips — Form Validation, Links, and Isomorphic Components

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.

Form Input Validation with React

We can do form validation with our own checks.

For instance, we can do the value checks within the submit handler.

We can write:

class Signup extends React.Component{
  constructor(props){
    super(props);
     this.state = {
       isDisabled:true
     }
     this.submitForm = this.submitForm.bind(this);
  }

  handleChange(e){
    const target = e.target;
    const value = target.value;
    const name = target.name;
    this.setState({
      [name]: value
    });

    if (e.target.name==='firstname'){
      if (e.target.value === '' || e.target.value === null){
        this.setState({
          firstnameError: true
        })
      } else {
        this.setState({
          firstnameError: false,
          firstName: e.target.value
        })
      }
    }

    if (e.target.name==='lastname'){
      if(e.target.value==='' || e.target.value === null) {
        this.setState({
          lastnameError: true
        })
      } else {
        this.setState({
          lastnameError:false,
          lastName:e.target.value
        })
      }
    }

  }

  submitForm(e){
    e.preventDefault();
    const data = {
     firstName: this.state.firstName,
     lastName: this.state.lastName
    }
  }

  render(){
    return (
      <form>
        <div>
          <input type="text" id="firstname" name="firstname" placeholder="firstname" onChange={(e)=>{this.handleChange(e)}} />
          <label htmlFor="firstname">firstname</label>
            {this.state.firstnameError ? 'Please Enter some value' : ''}
        </label>
        <div>
           <input type="text" name="lastname" placeholder="lastname" onChange={(e)=>{this.handleChange(e)}} />
            <label htmlFor="lastname">lastname</label>
              {this.state.lastnameError ? '>Please Enter some value' : ''}
            </label>
         </div>
         <button onClick={this.submitForm}>Signup</button>
      </form>
    );
  }
}

We have the first name and last name fields.

We watch for their inputted values and check for them in the handleChange method.

target.name has the value of the name attribute.

target.value has the inputted value.

And then in each field, we check if it’s filled in.

In the submitForm method, we get the data and then submit it.

We’ve to call preventDefault to stop the default submit behavior.

To make our lives easier, we can use a package like React Hook Forms to do form validation.

For instacne, we can write:

import React from "react";
import useForm from 'react-hook-form';

function Form() {
  const { useForm, register } = useForm();
  const contactSubmit = data => {
    console.log(data);
  };

  return (
    <form onSubmit={contactSubmit}>
      <div className="col-md-6">
        <fieldset>
          <input name="name" type="text" size="30" placeholder="Name" ref={register} />
          <br />
          <input name="email" type="text" size="30" placeholder="Email" ref={register} />
        </fieldset>
        <fieldset>
          <button id="submit" value="Submit">
            Submit
          </button>
        </fieldset>
      </div>
    </form>
  );
}

We use the useForm hook that comes with the package.

And then we call register returned from useForm to get register the input fields so that we get the form values with the submit handler.

The values are in the data parameter of the contactSubmit function.

Importing CSS files in Isomorphic React Components

In isomorphic React components, we can check for the environment before we import our CSS.

For instance, we can write:

if (process.env.BROWSER) {
  require("./style.css");
}

We check the environment variables before we import the CSS.

We import only in the browser environment.

We can then define a Webpack plugin to set the environment variable:

plugins: [
  // ...
  new webpack.DefinePlugin({
    "process.env": {
      BROWSER: JSON.stringify(true)
    }
  })
]

How to Render Child Components in React Recursively

We can render child components recursively by rendering the same component within the component.

For instance, we can write:

import React, { Component, PropTypes } from 'react'

export default class Comments extends Component {

render() {
    const { comments } = this.props;

    return (
      <div>
        {comments.map(comment =>
          <div key={comment.id}>
            <span>{comment.content}</span>
            {comment.comments && <Comments comment={comment.comments} />}
          </div>
        )}
      </div>
    )
  }
}

Comments.propTypes = {
  comments: PropTypes.array.isRequired
}

We create a Comment component that takes a comments prop that’s rendered into an array of Comment components.

We make the comments prop required and an array so that we can render them if they’re passed in.

React-Router is Refreshing the Page when Using a Tag

To stop refreshing the page when we click an a tag, we should use the Link component.

For instance, we can write:

import React from "react";
import { Link } from 'react-router-dom';

export class App extends React.Component {
  render() {
    return (
      <Link to="/foo">Click Here</Link>
    )
  }
};

We use the Link tag with the to prop that has the route.

Conclusion

We can validate form inputs in many ways.

To make our lives easier, we should use a form validation library

Also, we check the environment before we import CSS in an isomorphic React component.

We use the Link component for links if we use React Router.

Categories
React Tips

React Tips — Errors and Redux, Commas Separated List, and Detect page

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.

Detecting User Leaving Page with React Router

React Router has the Prompt component to let us block navigation with a message.

For instance, we can write:

import { Prompt } from 'react-router'

const App  = () => (
  <React.Fragment>
    <Prompt
      when={shouldBlockNavigation}
      message='Are you sure you want to leave?'
    />
    {/* more components */}
  </React.Fragment>
)

We have the Prompt which takes a when prompt with a boolean expression that indicates when we want to block navigation.

message is the message to display when the user tries to leave.

It’ll block anything but not page refresh or closing.

To block refresh or closing, we’ve to set the onbeforeunload property to different values depending on whether navigation is blocked or not.

For instance, we can write:

componentDidUpdate = () => {
  if (shouldBlockNavigation) {
    window.onbeforeunload = () => true
  } else {
    window.onbeforeunload = undefined
  }
}

If navigation should be blocked when refreshing or closing the browser tab, then we set it window.onbeforeunload to a function that returns true .

Otherwise, we set it to undefined .

Avoid Extra Wrapping <div> in React

We can use a fragment to avoid wrapper an extra div outside our components.

For instance, we can write:

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

or:

render() {
  return (
    <>
      <ChildA />
      <ChildB />
      <ChildC />
    </>
  );
}

Deal with a Fetch Error in react-redux

We can use redux-thunk to create an async action that calls dispatch to dispatch synchronous actions on error.

For instance, we can write:

export function getData() {
  return dispatch => {
    dispatch({type: FETCH });

    httpClient.get('/data')
      .then(res => {
        dispatch({ type: FETCH_SUCCESS, data: res.body });
      })
      .catch(error => {
        dispatch({type: FAILED });
        dispatch({type: ADD_ERROR, error });
      });
  };
}

We have a thunk that gets data and calls dispatch to dispatch various actions.

In our errors reducer, we can write:

function errors(state = [], action) {
  switch (action.type) {
    case ADD_ERROR:
      return [...state, action.error];
    case REMOVE_ERROR:
      return state.filter((error, i) => i !== action.index);
    default:
      return state;
  }
}

We have the errors reducer that has the ADD_ERROR case to add errors and another case to remove the given error.

Then we can map the errors state to props by writing:

export default connect(
  state => ({
    errors: state.errors,
  })
)(App);

where App is a React component.

Tell the Version of React Running at Runtime in the Browser

We can get the React.version property to get the version of React running in the browser.

There’s also the:

npm view react version
npm view react-native version

to get the React version.

require(‘React’).version also works.

Remove the /#/ in the Browser with React Router

To remove the hash sign from the URL with React Roytee, we can use the BrowserRouter as the route root tag,.

For instance, we can write:

import BrowserRouter from 'react-router/BrowserRouter'

ReactDOM.render ((
  <BrowserRouter>
   {//...}
  <BrowserRouter>
), document.body);

We also need to rewrite the URLs to redirect to index.html so we won’t get errors when loading or refreshing the page:

# Setting up apache options
AddDefaultCharset utf-8
Options +FollowSymlinks -MultiViews -Indexes
RewriteEngine on

# Defining the rewrite rules
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f

RewriteRule ^.*$ ./index.html

This config is for Apache servers.

Render React Components Separated by a Comma by Using map and reduce

We can render React components with map and join by mapping the items to components.

Then we can use reduce to put commas between the components.

For instance, we can write:

class CommaList extends React.Component {
  render() {
     <div>
        {this.props.data
          .map(t => <span>{t}</span>)
          .reduce((combined, curr) => [combined, ', ', curr])}
     </div>
  }
}

We get the data prop, which is an array.

Then we call map to map them to components.

And then we call reduce to add commas between the components that are already joined with commas, which is stored in combined and the new component stored in curr .

Conclusion

We can detect situations when the users leave the page in React Router.

We can combine components in an array separated by commas with reduce.

Also, we can dispatch actions when errors occur with Redux.

Categories
React Tips

React Tips — Clicks, Watching Widths, Custom Links

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.

Manually Trigger Click Event in React

To manually trigger a click event in a React component, we can assign a ref to the DOM element.

And then we can call click on the ref.

For instance, we can write:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  render() {
    return (
      <div onClick={this.handleClick}>
        <input ref={input => this.inputElement = input} />
      </div>
    );
  }

  handleClick(e){
    this.inputElement.click();
  }
}

We have assigned the inputElement ref with a callback.

Then we click the input element in the handleClick method by calling click on the this.inputElement DOM object.

This also works in a function component:

const UploadsWindow = () => {
  const inputRef = useRef();

  const uploadClick = e => {
    e.preventDefault();
    inputRef.current.click();
  };

  return (
    <>
      <input
        type="file"
        name="fileUpload"
        ref={inputRef}
        multiple
        onClick={uploadClick}
      />
    </>
  )
}

We created a ref with the useRef hook and assigned it to the input.

Then, we have the click handler uploadClick function, which calls the click method on the input DOM element.

The current property has the DOM object that’s been assigned the ref.

Respond to the Width of an Auto-Sized DOM Element in React

To watch the width of the DOM elemnt on React, we can use the react-measure package.

To install it, we run:

yarn add react-measure

or:

npm install react-measure --save

Then we use it by writing:

import * as React from 'react'
import Measure from 'react-measure'

const Width = () => (
  <Measure bounds>
    {({ measureRef, contentRect: { bounds: { width }} }) => (
      <div ref={measureRef}>{width}</div>
    )}
  </Measure>
)

We have the Measure component, which has a callback with many properties as its parameter.

measureRef is a ref that we can use to get the element.

contentRect has the information about the element that’s been assigned to the measureRef .

width has the width.

So we watch the element’s width changes with the width property.

There’s also the react-sizeme component that can also be used to get the size of the component.

For instance, we can write:

import SizeMe from 'react-sizeme';

class Circle extends Component {
  render() {
    const { width, height } = this.props.size;

    return (
     <svg width="100" height="100">
       <circle cx="150" cy="100" r="80" fill="green" />
     </svg>
    );
  }
}

export default SizeMe()(Circle);

It comes with the SizeMe higher-order component, which we can pass our component into it to get the width and height of it.

They’re available via the props since we called the SizeMe higher-order component with it.

React Context Outside of Render Function

With a function component, we can use the useContext hook to let us access the context anywhere in our component.

For instance, we can write:

const App = () => {
  const contextValue = useContext(AppContext);
  // ...
}

In a class component, we can set the static contextTyoe property so that we can use the context anywhere in our class component.

We access the context with the this.context property.

For instance, we can write:

class App extends React.Component {
  componentDidMount() {
    const value = this.context;
  }

  componentDidUpdate() {
    const value = this.context;
    /* ... */
  }

  componentWillUnmount() {
    const value = this.context;
    /* ... */
  }

  render() {
    const value = this.context;
    /* render content */
  }
}

App.contextType = AppContext;

this.context is available anywhere once we set the contextType property to a context.

Wrapping a React Router Link in an HTML Button

We can wrap the Link component with anything we want to display.

For example, we can write:

<Link to="/profile">
   <button type="button">
     click me
   </button>
 </Link>

We can also embed components:

<Link to="/profile">
   <Button>
     click me
   </Button>
 </Link>

Conclusion

We can trigger the click event by assigning an element to a ref and calling methods on it.

Also, we can use contexts outside of the render function.

There’re libraries that let us watch for changes in the dimension of a component.

React Router Link components can have elements or components inside it.

Categories
React Tips

React Tips — Watching Props, Downloads, and Media Queries

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.

Run Async Code on Update of State with React Hooks

We can watch for the change of the state with the useEffect hook.

The 2nd argument takes an array that can hold the values that we want to watch.

When they change, the callback in the first argument will run.

For instance, we can write:

function App() {
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    if (loading) {
      doSomething();
    }
  }, [loading]);

  return (
    <>
      <div>{loading}</div>
      <button onClick={() => setLoading(true)}>click Me</button>
    </>
  );
}

We have the useEffect hook that watches the loading state.

If it changes, then the callback will load.

It’ll change when we click the click me button.

It sets the loading state to true .

How to Download Fetch Response in a React Component as a File

We can download the response retrieved by the Fetch API as a file by converting the result to a blog.

Then we can download it by clicking on an invisible link.

For instance, we can write:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.linkRef = React.createRef();
  }

  componentDidMount() {
    fetch('./file.pdf')
      .then(res => {
        return res.blob();
      }).then(blob => {
        const href = window.URL.createObjectURL(blob);
        const a = this.linkRef.current;
        a.download = 'file.pdf';
        a.href = href;
        a.click();
        a.href = '';
      })
      .catch(err => console.error(err));
  }

  render() {
    return (
      <a ref={this.linkRef}/>
    );
  }
}

We have a link assigned to our ref.

Then with the fetch function, we make a GET request for file.pdf .

Then we convert that to a blob with res.blob()

Once we did that, we pass the blob into the createObjectURL method.

Then we get the link and set the download property to set the file name.

href is set to the object URL we created.

And then we call click to start the download.

And we clear the link by setting href to an empty string.

Updating State with Props on React Child Component

In a child component, we can update the states with props by returning a state in getDerivedStateFromProps.

For instance, we can write:

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    }
  }

  static getDerivedStateFromProps(props) {
    return {
      count: props.count * 2
    }
  }

  // ...
}

We get the count from the props and then we doubled it and return that as the value of the count state.

It’s a static method, unlike most other class component methods.

It’s called every time a component is rendered, regardless of the update.

It’s asynchronous so it’s consistent with other methods, which are also async.

We shouldn’t commit side effects in the method.

If we need to commit side effects, we should do them elsewhere.

Inline CSS Styles in React and Media Queries

We can add CSS styles in the form of inline JavaScrip with the react-responsive package.

It supports adding media queries.

We can install it by running:

npm install react-responsive --save

Then we can write:

import React from 'react'
import { useMediaQuery } from 'react-responsive'

const App  = () => {
  const isDesktopOrLaptop = useMediaQuery({
    query: '(min-device-width: 1224px)'
  })
  const isBigScreen = useMediaQuery({ query: '(min-device-width: 2000px)' })
  const isTablet = useMediaQuery({ query: '(max-width: 1500px)' })
  const isMobile = useMediaQuery({
    query: '(max-device-width: 1000px)'
  })
  const isPortrait = useMediaQuery({ query: '(orientation: portrait)' })

  return (
    <div>
      <p>{isBigScreen && 'big screen'}</p>
      <p>{isTablet && 'tablet screen'}</p>
      <p>{isMobile && 'mobile screen'}</p>
      <p>{isPortrait && 'portrait screen'}</p>
    </div>
  )
}

It comes with th useMediaQuery hook that lets us add media queries for the screen with a given width or orientation.

We have one for the big screen, media query, mobile, and portrait screens.

They all return boolean according to screen size and orientation.

Then we can use them in our JSX code to create responsive layouts.

Conclusion

There are packages for adding media queries with JavaScript.

We can run async code with useEffect .

We can also watch for prop changes and does updates accordingly.

And we can download files in a React component.