Categories
React Tips

React Tips — Redirect, Error Handling and Redux, and .env Files

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 Button Redirect Page on Click

We can redirect to a page when we click on an element by getting the history object.

For instance, we can write:

import React from 'react';
import { useHistory } from "react-router-dom";
function LoginPage () {
  const history = useHistory();
  const onClick = () => {
    history.push('new-page');
  }

  return (
    <div>
      <button
        onClick={onClick}
      >
        Login
      </button>
    </div>
  );
}
export default LoginPage;

We get the native history object with useHistory

Then we define the onClick function to call history.push to navigate to a new page.

If we’re using class components, we can write:

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

class LoginPage extends Component {
  constuctor() {
    this.routeChange = this.routeChange.bind(this);
  }

  onClick() {
    this.props.history.push('forgot-password');
  }

  render() {
    return (
      <div>
        <button onClick={onClick}>Forgot password?</button>
      </div>
    );
  }
}

export default withRouter(LoginPage);

We have the LoginPage class component.

To make the history prop available to the component, we pass it to withRouter .

We have the onClick method that calls the this.props.history.push method to navigate to the new page.

The routerChange method has to be bound to the component with bind so that we set the component class as the value of this .

Render Boolean Value in JSX

We can render boolean value in JSX by converting it to a string first.

For instance, we can write:

Boolean Value: {bool.toString()}

or:

Boolean Value: {String(bool)}

or:

Boolean Value: {'' + bool}

or:

{`Boolean Value: ${bool}`}

or:

Boolean Value: {JSON.stringify(bool)}

There are many ways to convert a boolean value into a string.

They’re all good except for the concatenation, which may be confusing.

Using event.target with React Components

We can use event.target to get a DOM element’s properties.

We can use the dataset property to get attributes prefixed with the data- prefix.

They’re considered custom attributes that let us pass data around with an element.

For instance, if we have a button, then we can write:

<button
  data-foo="home"
  data-bar="home"
  onClick={this.props.onClick}
/>
  Button
</button>

Then we can write:

onClick(e) {
   console.log(e.target.dataset.bar, e.target.dataset.foo);
}

to get the foo and bar properties from the button that we clicked with the dataset property.

dataset.foo has the value of the data-foo attribute.

dataset.bar has the value of the data-bar attribute.

Adding a .env File to React Project

If we have a create-react-app project, we can add an .env file to add the environment variables.

Inside the file, any keys that are prefixed with the REACT_APP_ prefix are read into the app.

So in our .env file, we can write:

REACT_APP_API_KEY=secret

We can then use the environment variable values by writing:

fetchData() {
  fetch(`https://example.com?api-key=${process.env.REACT_APP_API_KEY}`)
    .then((res) => res.json())
    .then((data) => console.log(data))
}

We read the environment variable value with the process.env object.

How to Pass Multiple Parameters to Input’s onChange Handler

We can pass in multiple parameters to an input’s onChange handler.

To do that, we can write:

<Input
  type="text"
  value={this.state.name}
  onChange={this.onChange.bind(this, this.state.user.id)}
/>

Then we can define our onChange method by writing:

onChange(`userId`, event) {
  const newName = event.target.value;
},

We have whatever we pass in as the first argument.

And the last argument is the object.

How to Catch and Handle Error Response 422 with Redux and Axios

We can call dispatch to dispatch the action within a React component.

For instance, we can write:

axios({
  method: 'post',
  responseType: 'json',
  url: `${SERVER_URL}/login`,
  data: {
    username,
    password
  }
})
 .then(response => {
   dispatch(setUser(response));
 })
 .catch(error => {
   dispatch({ type: AUTH_FAILED });
   dispatch({ type: ERROR, payload: error.data.error.message });
 });

We make a POST request with Axios.

Then in the then callback, we get the response and call dispatch and our setUser action creator.

And then we call the catch method with a callback to handle errors.

We call dispatch with or without a payload.

Calling dispatch would update the store with the new state value.

Conclusion

We can redirect pages on click.

And we can handle errors with Redux by calling dispatch to update the stores.

Booleans can be rendered if we convert them to a string.

Categories
React Tips

React Tips — Loading Data, Redux Stores, and Styled 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.

setState on Parent Inside Child Component

We can pass a function from the parent to the child component.

Then we can call it inside the child to set the state if the parent.

For instance, we can write:

import React, { useState, useEffect, useCallback, useRef } from "react";

function Parent() {
  const [parentState, setParentState] = useState(0);

  const wrapperSetParentState = useCallback(val => {
    setParentState(val);
  }, [setParentState]);

  return (
    <div>
      <Child
        setParentState={wrapperSetParentState}
      />
      <div>{parentState}</div>
    </div>
  );
};

function Child({ setParentState }) {
  const [childState, setChildState] = useState(0);

  useEffect(() => {
    setParentState(childState);
  }, [setParentState, childState]);

  const onSliderChange = e => {
    setChildState(e.target.value);
  };

  return (
    <div>
      <input
        type="range"
        min="1"
        max="100"
        value={childState}
        onChange={onSliderChange}
      ></input>
    </div>
  );
};

We created the Child component with a slider input that takes a range of values.

Also, we defined the onSliderChange function into the onChange prop to watch for changes.

We set the e.target.value , which has the slider’s value as the value of the childState.

We also watch the changes for the childState to watch for changes for it.

And we called setParentState to call the function from the Parent that we passed into the props.

It set’s the parentState value from the parent,

We then display the latest value of the parentState in Parent .

useCallback lets us cache the value of parentState if it hasn’t changed.

React Router v4 <NavLink> vs <Link>

NavLink adds an active class to the link when it’s navigated to so that we can style it differently from the other links.

It takes an activeClassName prop to let us change the class name.

For instance, we can write:

<NavLink to="/" activeClassName="active">profile</NavLink>

We can make the dynamic to style the link the way we want.

React Render String with Non-Breaking Spaces

We can style the white-space: nowrap style to display strings with non-breaking spaces.

For instance, we can write:

<div style="white-space: nowrap">no breaks</div>

or

<div style={{ whiteSpace: 'nowrap' }}>no breaks</div>

React Async Rendering of Components

We can render async data by providing a loading message that’s displayed when something is loading.

If there’s data, then we display that instead of the loading message.

For instance, we can write:

import React from 'react';

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

  componentDidMount(){
    fetch('https://randomuser.me/api')
      .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.first}</div>
      }
    </div>);
  }
}

We display a loading message when the data state is null .

Otherwise, we show the data that we want to display from the API.

We fetch the data in componentDidMount , which means that the data will be fetched when the component mounts.

Dispatch Action on App Load with React-Redux

We can call mapStateToProps to map the states from the Redux stores as props of a component.

mapDispatchToProps match the action dispatch functions to props of a component.

For instance, we can write:

class App extends Component {
  componentDidMount() {
    this.props.getUser()
  }

  render() {
    return this.props.isReady
      ? <div> ready </div>
      : <div>not ready</div>
  }
}

const mapStateToProps = (state) => ({
  isReady: state.isReady,
})

const mapDispatchToProps = dispatch => {
  return {
    getUser: () => dispatch(getUserActionCreator())
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App)

We create a mapStateToProps function that takes a state parameter, which has the state parameter with the Redux state.

Then we can get the isReady state from it and map it to the isReady prop in the key.

getUser is mapped to a function that calls dispatch to dispatch an action.

getUseractionCreator returns an object that has the type and payload properties to pass those to the reducer and run the right action.

With function components, we can write:

import { appInit } from '../store/actions';
import { useDispatch } from 'react-redux';

const appInit = () => ({ type: APP_INIT });

export default App() {
  const dispatch = useDispatch();
  useEffect(() => dispatch(appInit()), [ dispatch ]);

  return (<div>something</div>);
}

We call the useDispatch hook to let us dispatch actions returned from the appInit function, which also has the type and payload properties.

Conclusion

We can dispatch actions with React-Redux to manipulate the store.

Also, we can call parent component’s functions in a child component.

Different things can be rendered our way when we load data.

Categories
React Tips

React Tips — Get Data, Check Scrolling, and Way Use React Router Properly

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.

‘You should not use Route or withRouter() outside a Router when using react-router 4’ Error with the styled-components Library

To fix this error, we should make sure that we wrap the BrowserRouter component around our app.

For instance, we can write:

import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
   <BrowserRouter>
     <App />
   </BrowserRouter>
, document.getElementById('root'));

Listening to Window Events from Components

We can listen to events by attach event listeners in the componentDidMount method.

Then the listener is added when the component mounts.

We can remove the listen with removeEventListener in the componentWillUnmount to clean it up.

For instance, we can write:

class Home extends Component {
  constructor(props) {
    super(props)
    this.handleScroll = this.handleScroll.bind(this);
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll(e) {
    console.log('scrolled');
    console.log(e);
  }

  render() {
    return (
     <div>
       <Foo />
       <Bar />
       <Baz />
     </div>
    );
  }
}

We added the scroll event listener in compoonentDidMount .

The handler is the this.handleScroll method.

Then we have the removeEventListener method call within componentWillUnmount .

“Using string literals in ref attributes is deprecated (react/no-string-refs)” Lint Warning

We shouldn’t be using string refs since they’re being deprecated.

Instead, we can use createRef or callback refs.

For instance, we can write:

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

  render() {
    return (
      <div>
        <button ref={this.btnRef} onClick={this.handleClick}>click me</button>
      </div>
    );
  }
}

The ref is created with createRef .

We assigned the ref to the button with the ref prop.

Also, we can assign a ref with a callback as follows:

class App extends Component {
  constructor() {
    super();
    this.btnRef;
    this.state = { clicked: false };
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(){
    //...
  }

  render() {
    return (
      <div>
        <button ref={(el) => this.btnRef = el} onClick={this.handleClick}>click me</button>
      </div>
    );
  }
}

We get the element with the el parameter and then set it to this.btnRef .

Set State of Response from Axios in React

We can set the state inside the callback.

For instance, we can write:

axios.get('/url')
 .then((response) => {
   this.setState({ events: response.data })
 })
.catch(function (error) {
   console.log(error);
});

We make a GET request to a URL, then call setState on it.

We’ve to use an arrow function so that we can access the correct this , which is the component itself.

A full example would be the following:

import React from 'react';
import axios from 'axios';
export default class App extends React.Component {
  state = {
    persons: []
  }

  componentDidMount() {
    axios.get(`https://jsonplaceholder.typicode.com/users`)
      .then(({ data }) => {
        const persons = data;
        this.setState({ persons });
      })
  }

  render() {
    return (
      <div>
        { this.state.persons.map(person => <p>{person.name}</p>)}
      </div>
    )
  }
}

We make the same request and get the data from the data property of the response,

Then we call setState to update the persons state.

In the render method, we render the persons state array into paragraphs.

Detecting When User Scrolls to Bottom of div with React

We can listen for scroll events.

In the scroll event handler, we can get the getBoundClientRect method’s bottom property and compare it to the window.innerHeight to see of the div is at the bottom of the div.

For instance, we can write:

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

  isBottom(el) {
    return el.getBoundingClientRect().bottom <= window.innerHeight;
  }

  componentDidMount() {
    document.addEventListener('scroll', this.trackScrolling);
  }

  componentWillUnmount() {
    document.removeEventListener('scroll', this.trackScrolling);
  }

  trackScrolling(){
    if (this.isBottom(headerRef)) {
      document.removeEventListener('scroll', this.trackScrolling);
    }
  };

  render() {
    return (
      <div ref={this.headerRef}>
        ...
      </div>
    }
  }
}

We create the ref with the createRef in the constructor,.

Then in componentDidMount , we listen to the scroll event.

We added the trackScrolling method to listen to the scroll event.

Then we check is we scrolled to the bottom of the div with getBoundingClientRect ‘s returned object to check if we scrolled to the bottom of the div.

Conclusion

There are various ways to check for scrolling.

Also, we shouldn’t use string refs.

And can get data from Axios and set the state to render the data.

Categories
React Tips

React Tips — External URLs, Timers, and Hover Effect

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.

Wait for setState to Finish Before Triggering a Function

We can wait for setState to finish before triggering a function by passing in a function as a 2nd argument of setState .

For instance, we can write:

this.setState({
  firstName,
  lastName,
  age
}, () => {
  console.log(this.state) ;
})

We called setState with the object with the states first.

Then we run our callback to get the latest value of this.state .

External Link with React Router

We can add an external link by passing in a component to redirect to an external link.

For instance, we can write:

<Route path='/external-site' >
  {() => {
     useEffect(() => {
       window.location.href = 'https://example.com';
     }, [])
     return null;
  }}
</Route>

We used the Router component with the path prop to set the path.

Then in our component, we redirect to an external URL by setting the URL as the value of window.location.href .

And we return null to render nothing.

We can also redirect directly in componentDidMount :

class RedirectPage extends React.Component {
  componentDidMount(){
    window.location.replace('http://www.example.com')
  }

  render(){
    return null;
  }
}

Access a Hover State in React

We can set the hove state by listening to the mouseenter and mouseleave events.

For instance, we can write:

<div
  onMouseEnter={this.onMouseEnter}
  onMouseLeave={this.onMouseLeave}
>
  foo
</div>

We can pass in event handlers to the onMouseEnter and onMouseLeave props.

Then we can run code within those methods to set the hover state.

PropTypes in Functional Stateless Component

We can set the prop types in the functional stateless component.

For instance, we can write:

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

const Name = ({ name }) => <div>hi {name}</div>;

Name.propTypes = {
  name: PropTypes.string
};

Name.defaultProps = {
  name: "james"
};

We created the Name component with the propTypes property.

Then we set the data type of the name prop with it.

We can also set the default value for the name prop.

We’ve to install the propt-types package to set types for the props.

setTimeout() in React Components

We can use setTimeout in React components by calling setTimeout in componentDidMount and then clearing the timer within the componentWillMount method.

For instance, we can write:

class App extends React.Component {
  constructor() {
    this.state = { position: 0, timer: undefined };
  }

  componentDidMount() {
    const timer = setTimeout(() => this.setState({ position: 1 }), 3000)
    this.setState({ timer });
  }

  componentWillUnmount(){
    clearTimeout(this.state.timer);
  };

  render() {
    return (
      <div>
        {this.state.position}
      </div>
    );
  }
}

We called setTimeout with a callback with the timeout time span in componentDidMount to get the timer when the component loads.

It returns a timer object that we can call clearTimeout with to clear the resources for the timer when the component unmounts./

We have the timer state to set the timer returned from setTimeout to the state.

Then we in componentWillUnmount , we call clearTimeout to clear the timer.

setInterval in a React Component

Like with setTimeout , we can call setInterval within a React component.

It’s pretty much the same as setTimeout except that we can setInterval and clerInterval .

For instance, we write:

class App extends React.Component {
  constructor() {
    this.state = { position: 0, timer: undefined };
  }

  componentDidMount() {
    const timer = setInterval(() => this.setState(state => ({ position: state.position + 1 })), 3000)
    this.setState({ timer });
  }

  componentWillUnmount(){
    clearInterval(this.state.timer);
  };

  render() {
    return (
      <div>
        {this.state.position}
      </div>
    );
  }
}

We called setInterval in componentDidMount to create a timer to run code periodically.

In the setInterval callback, we update the position state every 3 seconds.

Then in componentWillUnmount , we call clearInterval to clear the timer.

With function components, we can do the same thing.

For instance, we can write:

import React, { useState, useEffect } from 'react';

const App = () => {
  const [position, setPosition] = useState(0);
  const timer = () => setPosition(position => position + 1);

  useEffect(() => {
    const timer = setInterval(timer, 1000);
    return () => clearInterval(timer);
  }, []);

  return <div>{position}</div>;
};

We have the useState hook to update the position state with setPosiitin .

Then we have the useEffect hook to create a timer when the component loads.

Then function we return in the useEffect callback removes the timer with clearInterval .

The empty array in the 2nd argument ensures that the useEffect callback only runs when App first loads.

Conclusion

We can create a component to redirect to an external URL.

Also, we can use setTimeout and setInterval in our components.

To set prop types, we can use the prop-types package.

Categories
React Tips

React Tips — Detect KeyPress, Unique IDs, and Remove Items

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.

Generate Unique IDs for Form Labels in React

We can generate unique IDs with the Lodash or Underscpre’s uniqueId method.

For instance, we can write:

class App extends React.Component {
  `constructor(props) {
    super(props);
    this.id = _.uniqueId("form-");
  }

  render() {
    const id = this.id;
    return (
      <div>
        <input id={id} type="text" />
        <label htmlFor={id}>label</label>
      </div>
    );
  }
}`

We called uniqueId and assigned the returned value as the value of the id prop.

The argument for the method is the prefix for the ID.

With function components, we can write:

import React, { useState } from 'react';
import uniqueId from 'lodash/uniqueId';

const App = (props) => {
  const [id] = useState(uniqueId('form-'));
  return (
    <div>
      <input id={id} type="text" />
      <label htmlFor={id}>label</label>
    </div>
  );
}

We imported the uniqueId function and then put it in useState .

This way, we can get the ID as variable and use it in our form child elements.

Detect Esc Key Press in React

We can detect the Esc key by adding a keydown event handler into our component.

For instance, we can write:

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

  onKeyPress(event){
    if(event.keyCode === 27) {
      //...
    }
  }

  componentDidMount(){
    document.addEventListener("keydown", this.onKeyPress, false);
  }

  componentWillUnmount(){
    document.removeEventListener("keydown", this.onKeyPress, false);
  }

  render(){
    return (
      <input />
    )
  }
}

We add an event listener for the keydown event by calling documebnt.addEventListener in the componentDidMount method.

This will ensure that the event listener is added when the component mounts.

Likewise, we can removeEventListener to remove the event listener to ensure that it’s unloaded when the component unmounts.

this.onKeypress is the event handler.

In the method, we check the keyCode property to get the code for the key pressed.

27 is the code for the Esc key.

With function components, we can use the useEffect hook to add and remove the listener.

For instance, we can write:

import React, { useEffect } from 'react';

const App = () => {

  useEffect(() => {
    const handleEsc = (event) => {
       if (event.keyCode === 27) {
        console.log('Close')
      }
    };
    window.addEventListener('keydown', handleEsc);

    return () => {
      window.removeEventListener('keydown', handleEsc);
    };
  }, []);

  return(<p><input /></p>);
}

We have the useEffect hook with a callback to add the keydown listener.

We call addEventListener when the component mounts with addEventListener .

The empty array in the 2nd argument ensure that it loads only when the component mounts,

We call removeEventListener when the component unmounts to remove the listener when it unmounts.

The event listener code is the same as the previous example.

Delete Item from State Array in React

We can delete an item from a state array by calling splice on the original array and then calling setState to set that as the new value of the state array.

For instance, we can write:

removePeople(e) {
  const people = [...this.state.people];
  const index = array.indexOf(e.target.value);
  if (index !== -1) {
    people.splice(index, 1);
    this.setState({ people });
  }
},

First, we make a copy of the array so that we can modify it without changing the original array.

Then we get the index that we want to remove.

Then we call splice to remove the item from the array copy.

And then we call setState to set that as the new value.

We can also use the filter method to return a new array that includes the items that we want to keep.

For example, we can write:

class ItemsList extends Component {
  constructor() {
    this.state = {
      itemsList: [
        {
          id: 1,
          name: 'All Items',
        }, {
          id: 2,
          name: 'In Stock Items',
        }
      ],
    }
     this.removeItem = this.removeItem.bind(this)
  }

  removeItem(deleteItemId) {
     this.setState({
       itemsList: this.state.itemsList.filter(item => item.id != deleteItemId)
        })
   }

  render(){
    return <div />
  }
}

We called filter to return a new array that includes only the items with id value other than deleteItemId .

Then we call setState to set that as the new value of itemsList state.

Conclusion

We can generate unique ID with Underscore or Lodash methods.

There are a few ways to remove an item from a state array.

And there are multiple ways to detect Esc key press.