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.

Categories
React Tips

React Tips — Styles, Clone Element, and Nav Bar

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.

Fix ‘style prop expects a mapping from style properties to values, not a string’ Error

We’ve to pass in an object to the style prop.

For instance, we can write:

<span style={{ float: 'left', paddingRight: '5px' }} >foo</span>

We pass in an object with camel-cased properties instead of kebab-case.

Also, we can import styles from a file with the import keyword.

For instance, we can write:

styles.css

.color{
  color: "red";
  background: "#0f0";
}

Then we write:

import './styles.css';

const Button = (props) => {
  return (
    <div>
      <span className="color">{props.age}</span>
    </div>
  );
};

const infos = {
  age: 20
};

ReactDOM.render(<Button {...infos} />, mountNode);

We import the styles.css and then the styles will be applied.

React useReducer Async Data Fetch

useReducer can be used instead of useState if we’re changing a state that’s set after lots of computation.

If we have complex state logic with multiple sub-values in the state, or when the next state depends on the previous one, then we can use this hook.

For instance, we can write:

const initialState = {};

function reducer(state, action) {
  switch (action.type) {
    case 'profileReady':
      return action.payload;
    default:
      throw new Error();
  }
}

function App(props) {
  const [profile, setProfile] = React.useReducer(reducer, initialState);

  useEffect(() => {
    reloadProfile()
      .then((profileData) => {
        setProfile({
          type: "profileReady",
          payload: profileData
        });
    });
  }, []);

  return (
    <div>{profile.name}</div>
  );
}

We have a reducer that sets the state.

And we have an initial state that we can pass in.

We can pass them both into the useReducer hook.

It returns the state and the state setter function in this order.

Then we can use that with the useEffect to get data and set it.

The empty array in the 2nd argument make sure that the callback is only run only when the component is loaded.

How to Refresh a Page Using React Router Link

We can reload a page without using anything from React Router.

For instance, we can write:

window.location.reload();

to reload the page.

Create a Nav Bar with React Router

To create a navbar with React Router, we use the components that are bundled with React Router to create the routes.

For instance, we can write:

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";

export default function App() {
  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
            <li>
              <Link to="/dashboard">Dashboard</Link>
            </li>
          </ul>
        </nav>

        <Switch>
          <Route path="/about">
            <About />
          </Route>
          <Route path="/dashboard">
            <Dashboard />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </div>
    </Router>
  );
}

function Home() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function Dashboard() {
  return <h2>Dashboard</h2>;
}

We create a few components that we use as routes.

Then we use the in the Switch component to create our routes.

We have the Route component inside it and we nest the component we want to display inside.

The navbar is created with the nav component.

And inside it, we have the Link components to create the links to display the route components.

to is the path of the component that we want to display.

And it should match one of the path values in the Switch .

To do navigation, we can call history.push to navigate.

For instance, we can write:

<a onClick={() => history.push('dashboard') }>Dashboard</a>

to navigate programmatically.

Assign the Correct Typing to React.cloneElement When Giving Properties to Children

We can set the type of the child component to the React.ReactElement type.

For instance, we can write:

return React.cloneElement(child as React.ReactElement<any>, {
  name: this.props.name,
  age: this.props.age
});

if child is an element.

We can also use the isValidElement type guard.

For example, we can write:

if (React.isValidElement(child)) {
  return React.cloneElement(child, {
    name: this.props.name,
    age: this.props.age
  });
}

This will let the TypeScript compiler determine the type automatically without adding any data type assertions.

Conclusion

cloneElement can be used with child elements in React by setting the right type or using a type guard.

Styling can be done with various items.

We can create a navbar easily with React Router.