Categories
React Tips

React Tips — Titles, Default Props, and Hooks with Function 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.

Render New React Component on Click

We can render a new React component on click if we set a state so that the component can be rendered.

For example, we can write:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showComponent: false,
    };
    this.onClick= this.onClick.bind(this);
  }

  onClick() {
    this.setState({
      showComponent: true,
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.onClick}>click me</button>
        {this.state.showComponent ?
           <Foo /> :
           null
        }
      </div>
    );
  }
}

We have a button that runs the this.onClick method on click.

It changes the showComponent state to true .

Then we can make the Foo component show when this.state.showComponent is true .

Keep document.title Updated in a React App

To make updating the title of a React app easy, we can use the react-document-title package to do it.

To install it, we run:

npm install --save react-document-title

Then we can use it by writing:

function App() {
  return (
    <DocumentTitle title='My App'>
      hello world
    </DocumentTitle>
  );
}

Then ‘My App’ will be the title of our React app.

When we switch components, we can switch the title of the document.

For instance, we can write:

function HomePage() {
  return (
    <DocumentTitle title='Home'>
      <h1>home page.</h1>
    </DocumentTitle>
  );
}

We just wrap our component with the DocumentTitle component to set the title.

It also works with class components:

class NewArticlePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = { title: 'Untitled' };
  }

  render() {
    return (
      <DocumentTitle title={this.state.title}>
        <div>
          <input
            value={this.state.title}
            onChange={(e) => this.setState({ title: e.target.value         })}
          />
        </div>
      </DocumentTitle>
    );
  }
}

We can make the state dynamic by passing in the state variable into the title prop.

It also works with server-side rendered apps.

There’s also the react-helmet plugin which lets us set the page title and more.

To set the title with it, we use the Helmet component with the title element inside.

For instance, we can write:

import React from "react";
import {Helmet} from "react-helmet";

class App extends React.Component {
  render () {
    return (
      <div>
        <Helmet>
          <meta charSet="utf-8" />
          <title>My Title</title>
        </Helmet>
        {/* ... */}
      </div>
    );
  }
};

We can use it to add any element we can add in the head tag, including the title tag.

It also works with both client and server-side rendered apps.

Use React Hooks in a React Classic class Component

To use gooks in a class component, we can create a functional component that’s used as a higher-order component.

For instance, we can write:

const withHook = (Component) => {
  return WrappedComponent = (props) => {
    const someHookValue = useSomeHook();
    return <Component {...props} someHookValue={someHookValue} />;
  }
}

We used our useSomeHook hook in our withHook component.

Then we pass the hooks’s output value into the Component , which can be any component, including a class component.

Then we can use it by writing:

class Foo extends React.Component {
  render(){
    const { someHookValue } = this.props;
    return <div>{someHookValue}</div>;
  }
}

export default withHook(Foo);

We passed in Foo into our withHook higher-order component so that we can use our hook in the withHook HOC.

Call External Javascript Function from React Components

We can call external JavaScript functions from React components.

If we have something like:

<script>
  function test(){
    alert('hello world');
  }
</script>

Then we created a global function that we can call in our React components.

Inside it, we write:

componentWillMount() {
  window.test();
}

Default Prop is not Used when null is Passed

Default props are only set when undefined or nothing is passed in as the value of the prop.

Therefore, if we want to set the default prop value when null is set, we can write:

<Child count={count || undefined} />

If count is falsy, and null is falsy, we’ll pass in undefined as the value of count .

Therefore, the default prop value will be set.

Conclusion

We can render a new component on click if we set a state to make the component render.

document.title can be updated with plain JavaScript or with a package.

We can create higher-order components with hooks if we want to use hooks with a class component.

Default props are only set if the prop is undefined .

Categories
React Tips

React Tips — Spies, Global Events, and Nav 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.

Register Event with useEffect Hooks

We can register events within the useEffect callback.

For instance, we can write:

const App = () => {
  const [userText, setUserText] = useState('');

  const handleUserKeyPress = useCallback(event => {
    const { key, keyCode } = event;
    if (keyCode === 32) {
      setUserText(prevUserText => `${prevUserText}${key}`);
    }
  }, []);

  useEffect(() => {
    window.addEventListener('keydown', handleUserKeyPress);

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

  return (
    <div>
      <p>{userText}</p>
    </div>
  );
}

We listen to the keypress event on the window.

If we press the space key, then the key code will be registered.

Then we can use that to append the state string with the key text.

We just keep appending the key code to the state string.

Automatic Redirect After Login with React Router

We can automatically redirect after login with React Router.

To do that, we get the history object and call push on it.

For instance, we can write:

fetch('/login', {
  username,
  password
})
  .then(response => response.json())
  .then(data => {
    this.props.history.push("/");
  })

We call this.props.history.push to do the redirect.

The prop is available once we pass the component into the withRouter higher-order component.

Set Types on useState React Hook with TypeScript

To set the state of the useState hook, we can pass in a type parameter with the useState function.

For instance, we can write:

const [user, setUser] = useState<IUser>({ name: 'james' });

IUser is an interface that has the name string property.

For a full example, we can write:

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

interface IUser {
  name: string;
}

const App = () => {
  const [user, setUser] = useState<IUser>({ name: 'james' });
  const clickHander = (stateSetter: Dispatch<IUser>) => {
    stateSetter({name : 'james'});
  }

  return (
     <div>
      <button onClick={() => { clickHander(setUser) }}>Change Name</button>
    </div>
  )
}

setUser has the type Dispatch<IUser> .

Dispatch is from the React package.

The type parameter in Dispatch should match the type we pass into useState .

Jest spyOn Call on a Component

To check if a component’s method is called, we can use the jest.spyOn method to check if it’s called.

For instance, we can write the following test:

describe('simple test', () => {
  it('clicks it', () => {
     const app = shallow(<App />)
     const instance = app.instance()
     const spy = jest.spyOn(instance, 'onClick')
     instance.forceUpdate();

     const p = app.find('.button')
     p.simulate('click')
     expect(spy).toHaveBeenCalled()
 })
})

We check if the onclick method is called if we get the p element and call it.

First, we mount the App component with the shallow function.

Then we get the instance with the instance method.

Next, we call jest.spyOn on the component method that we expect to call if we click the button.

We call forceUpdate to update our component that we want to test with the spy.

Then we find the p element with the class button .

Then we call simulate('click') on that to click it.

And then we check if the mock function has been called.

This works for class components since they have instance methods.

How to set the Inline Style of background-color with React

We can set the inline style of background color with the backgroundColor property.

For instance, we can write:

<a style={{ backgroundColor: 'orange' }}>orange</a>

We set the backgroundColor to 'orange' with the camel-cased key.

Set activeClassName for Wrapper Element of Link or IndexLink in React Router

We can create a wrapper element for a link by creating a component.

The activeClassName value can be passed in from the props.

For instance, we can write:

import React, { Component } from 'react';
import { NavLink } from 'react-router-dom';

class NavHeaderextends Component {

  render (){
    return (
      <header>
        <ul>
          <li>
             <NavLink activeClassName="active" exact to="/">home</NavLink>
          </li>
          <li>
             <NavLink activeClassName="active" to="/about">About</NavLink>
          </li>
          <li>
             <NavLink activeClassName="active" to="/courses">profile</NavLink>
          </li>
        </ul>
      </header>
    );
  }
}

We use the NavLink component to create the navigation links.

activeClassName is a string that we can set to the class that’s applied when the link is active.

to is the path that the link goes to.

Conclusion

We can make links with special styles when it’s active with React Router’s NavLink component.

useEffect hooks can be used to listen to global events.

We can mock class instance methods with Jest spies.

React useState hooks can state change functions can have types added to them.

Categories
React Tips

React Tips — Sorting Arrays, Handling Clicks and Inputs

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.

Sort an Array of Objects in React and Render Them

We can sort an array of objects with the sort method.

Then we can call map to render the sorted entries.

For instance, in the render method or function component, we may write:

const myData = this.state.data
  .sort((a, b) => a.name > b.name ? 1 : -1)
  .map((item) => (
     <div key={item.id}> {item.name}</div>
  ));

We call the sort method sort the data by the name property.

We check if a.name > b.name is true .

Strings can be compared directly.

Use onClick with divs in React

We can use onClick with divs if we provide it a size.

For instance, we can write:

class App extends React.component {
  constructor() {
    this.state = {
      color: 'black'
    };
  },

  changeColor() {
    const newColor = this.state.color == 'white' ? 'black' : 'white';
    this.setState({
      color: newColor
    });
  },

  render() {
    return (
       <div>
          <div
             style = {{
                background: this.state.color,
                width: 100,
                height: 100
             }}
             onClick = {this.changeColor}
          >
          </div>
      </div>
    );
  }
}

We create a div with a background by passing in an object with the styles in the style prop.

We set the width and height to 100px so that we can display a div with nothing inside.

Then we can pass in a click handler to the onClick prop.

In the changeColor method, we just toggle between white and black for the color state.

Add a <br> Tag in React Between Two Strings

We can add a line break character in a string to add a line break.

Then we can use the white-space: pre-line style to make them display.

For instance, we can write:

render() {
   message = `Hello n World.`;
   return (
       <div className='new-line'>{message}</div>
   );
}

in our component.

Then we can add the following CSS:

.new-line {
  white-space: pre-line;
}

Clearing an Input Value After Form Submit in a React Component

We can clear an input value after form submit in a React component.

To do that, we write:

onHandleSubmit(e) {
  e.preventDefault();
  const name = this.state.name;
  this.props.searchByName(name);
  this.setState({
    name: ''
  });
}

We call preventDefault to stop the default submit behavior.

Then we get the name from the state which is what we inputted.

Then we call our search function.

And finally, we clear the input value by clearing the name state by assigning it an empty string.

Edit Multiple Input Controlled Components in React

We can edit multiple, input controlled components by providing their own change handlers.

For instance, we can write:

class Form extends React.Component {
  constructor() {
    this.state = {};
  }

  changeFirstName(event) {
    const contact = this.state.contact;
    contact.firstName = event.target.value;
    this.setState({ contact });
  }

  changeLastName(event) {
    const contact = this.state.contact;
    contact.lastName = event.target.value;
    this.setState({ contact });
  }

  changePhone(event) {
    const contact = this.state.contact;
    contact.phone = event.target.value;
    this.setState({ contact });
  }

  render() {
    return (
      <div>
        <input type="text" onChange={this.changeFirstName.bind(this)} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.changeLastName.bind(this)} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.changePhone.bind(this)} value={this.state.contact.phone}/>
      </div>
    );
  }
}

We have 3 inputs, one for the first name, one for the last name, and one for the phone number.

Then in each handler, we get the values with event.target.value and then assign it to the state.

Each handler is passed into the onChange prop of each input.

We’ve to call bind(this) to return a function that has the component instance as the value of this .

value is set to the state that the event handler change.

This way, the inputted values will be displayed.

A better way to do it is to set the name dynamically with computed property keys.

For example, we can write:

class Form extends React.Component {
  constructor() {
    this.state = {};
  }


  handleChange(propertyName, event) {
    const contact = this.state.contact;
    contact[propertyName] = event.target.value;
    this.setState({ contact: contact });
  }

  render() {
    return (
      <div>
        <input type="text" onChange={this.handleChange.bind(this, 'firstName')} value={this.state.contact.firstName}/>
        <input type="text" onChange={this.handleChange.bind(this, 'lastName')} value={this.state.contact.lastName}/>
        <input type="text" onChange={this.handleChange.bind(this, 'phone')} value={this.state.contact.phone}/>
      </div>
    );
  }
}

We have one change handler for all 3 inputs.

Then we can pass in the field as the 2nd argument of bind to set that as the first argument of the handler.

Conclusion

We can add change handlers for each input so that we can update their inputted values as the new state values.

We can sort arrays and render them.

Also, we can make empty divs clickable if we set a size for it.

Categories
React Tips

React Tips — Share Data, Mock Functions, and Local Storage

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.

Update the Context Value in Provider from the Consumer

We can update the context value from the provider if we pass in the function into the context.

For instance, we can write:

const MyContext = React.createContext({});

class Child extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: ""
    };
  }

  onChange(e){
    const name = e.target.value;
    this.setState({
      name
    });
    this.props.context.updateValue('name', name);
  }

  render() {
    return (
       <React.Fragment>
         <input onChange={this.onChange} />
       </React.Fragment>
    )
  }
}

const withContext = (Component) => {
  return (props) => {
    <MyContext.Consumer>
      {(context) => {
           return <Component {...props} context={context} />
      }}
    </MyContext.Consumer>
  }
}

Child = withContext(Child)

class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: "bar",
    };
  }

  updateValue = (key, val) => {
    this.setState({[key]: val});
  }

  render() {
    return (
      <MyContext.Provider value={{ state: this.state, updateValue: this.updateValue }}>
        <Child />
      </MyContext.Provider>
    )
  }
}

We create the context and pass the value from the Parent to the components in the context.

The object has the state and the updateValue function.

We then get the updateValue method from the props.context property, which is what we have.

Then we set the name by calling the updateValue method to set the name state of the Parent .

We’ve to remember to add the MyContext.Consumer to whatever component is consuming the context.

To do that, we created the withContext higher-order component to wrap any component with the context consumer.

getInitialState for React Class

We put the initial state in the constructor of a class component.

For instance, we can write:

import { Component } from 'react';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      foo: true,
      bar: 'no'
    };
  }

  render() {
    return (
      <div className="theFoo">
        <span>{this.state.bar}</span>
      </div>
    );
  }
}

We set the foo and bar states’ initial values in the constructor.

Using Local Storage with React

We can use the native local storage methods in React.

For instance, we can write:

import React from 'react'

class App extends React.Component {
  constructor(props) {
    super(props);
    const storedClicks = 0;

    if (localStorage.getItem('clicks')) {
      storedClicks = +(localStorage.getItem('clicks'));
    }

    this.state = {
      clicks: storedClicks
    };
    this.click = this.click.bind(this);
  }

  onClick() {
    const newClicks = this.state.clicks + 1;
    this.setState({ clicks: newClicks });
    localStorage.setItem('clicks', newClicks);
  }

  render() {
    return (
      <div>
        <button onClick={this.onClick}>Click me</button>
        <p>{this.state.clicks} clicks</p>
      </div>
    );
  }
}

We get the clicks from local storage if it exists.

Then we parse it if it exists and set that as the initial value of the clicks state.

Then in the render method, we have a button to update the clicks state and the local storage clicks value with the onClick method.

It updates the clicks state.

Also, we update the local storage’s clicks value after that.

Test a React Component Function with Jest

We can mock functions that our component depend on so that we can do testing with it.

For instance, we can write:

import React, { Component } from 'react';

class Child extends Component {
   constructor (props) {
      super(props);
   };

  render() {
      const { onSubmit, label} = this.props;
      return(
        <form  onSubmit={onSubmit}>
          <Button type='submit'>{label}</Button>
        </form >
      );
   };
};

export default class App extends Component {
  constructor (props) {
    super(props);
    this.label = “foo”;
  };

  onSubmit = (option) => {
    console.log('submitted');
  };

  render () {
    return(
      <div className="container">
        <Child label={this.label} onSubmit={this.onSubmit} />
      </div>
    );
  };
};

We can then mock the onSubmit function when we test the child by writing:

import React from 'react';
import { shallow } from 'enzyme';
import Child from '../Child';

const onSubmitSpy = jest.fn();
const onSubmit = onSubmitSpy;

const wrapper = shallow(<Child onSubmit={onSubmitSpy} />);
let container, containerButton;

describe("Child", () => {
  beforeEach(() => {
    container = wrapper.find("div");
    containerButton = container.find(“Button”);
    onSumbitSpy.mockClear();
  });

  describe("<Button> behavior", () => {
     it("should call onSubmit", () => {
       expect(onSubmitSpy).not.toHaveBeenCalled();
       containerButton.simulate(‘click’);
       expect(onSubmitSpy).toHaveBeenCalled();
     });
  });
});

We mount the component with the onSubmit prop populated by the onSubmitSpy , which is a mock function.

We tested by simulating a click event on the button of the Child component.

Then we check if the mocked function is called with toHaveBeenCalled .

Conclusion

We can pass around data with the context API.

Also, we can mock functions in with Jest so we can pass them in as props to test what we need to test.

Local storage can be used as-is in a React component.

Categories
React Tips

React Tips — GraphQL Queries, URL Parameters and React Router

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.

Make GraphQL Queries with React Apollo

We can make GraphQL queries with React Apollo by using the client.query method.

This is available once we update the component by calling withApollo function.

For instance, we can write:

class Foo extends React.Component {
  runQuery() {
    this.props.client.query({
      query: gql`...`,
      variables: {
        //...
      },
    });
  }

  render() {
    //...
  }
}

export default withApollo(Foo);

The client.query method will be available in the props once we call withApollo with our component to return a component.

The method takes an object that has the query and variables properties.

The query property takes a query object returned by the gql form tag.

variables has an object with variables that we interpolate in the query string.

We can also wrap our app with the ApolloConsumer component.

For example, we can write:

const App = () => (
  <ApolloConsumer>
    {client => {
      client.query({
        query: gql`...`,
        variables: {
          //...
        }
      })
    }}
  </ApolloConsumer>
)

We can make our query in here.

For function components, there’s the useApolloClient hook.

For instance, we can write:

const App = () => {
  const client = useApolloClient();
  //...
  const makeQuery = () => {
    client => {
      client.query({
        query: gql`...`,
        variables: {
          //...
        }
      })
    }
  }
  //...
}

The hook returns the client that we can use to make our query.

There’s also the useLazyQuery hook that we can use to make queries.

For instance, we can write:

const App = () => {
  const [runQuery, { called, loading, data }] = useLazyQuery(gql`...`)
  const handleClick = () => runQuery({
    variables: {
      //...
    }
  })
  //...
}

runQuery lets us make our query.

React Router Pass URL Parameters to Component

We can pass URL parameters if we create a route that allows us to pass parameters to it.

For instance, we can write:

const App = () => {
  return (
    <Router>
      <div>
        <ul>
          <li>
            <Link to="/foo">foo</Link>
          </li>
          <li>
            <Link to="/bar">bar</Link>
          </li>
          <li>
            <Link to="/baz">baz</Link>
          </li>
        </ul>

        <Switch>
          <Route path="/:id" children={<Child />} />
        </Switch>
      </div>
    </Router>
  );
}

function Child() {
  const { id } = useParams();

  return (
    <div>
      <h3>ID: {id}</h3>
    </div>
  );
}

We have a Child component that has the useParams hook.

It lets us get the URL parameters that we want and it’s passed in from navigation.

It returns the URL parameter as a key-value pair.

The keys are what we defined and the value is what we have passed when we navigate.

In App , we have the Link components with the paths.

And also we have the Switch components that have the route that takes the id URL parameter.

The Route has the route that we pass in. children has the component that’s displayed.

Preventing Form Submission in a React Component

There are several ways to prevent form submission in a React component.

If we have a button inside the form, we can make set the button’s type to be button.

For instance, we can write:

<button type="button" onClick={this.onTestClick}>click me</Button>

If we have a form submit handler function passed into the onSubmit prop;

<form onSubmit={this.onSubmit}>

then in th onSubmit method, we call preventDefault to stop the default submit behavior.

For example, we can write:

onSubmit (event) {
  event.preventDefault();
  //...
}

TypeScript Type for the Match Object

We can use the RouteComponentProps interface, which is a generic interface that provides some base members.

We can pass in our own interface to match more members if we choose.

For example, we can write:

import { BrowserRouter as Router, Route, RouteComponentProps } from 'react-router-dom';

interface MatchParams {
  name: string;
}

interface MatchProps extends RouteComponentProps<MatchParams> {}

const App = () => {
  return (
    <Switch>
      <Route
         path="/products/:name"
         render={({ match }: MatchProps) => (
            <Product name={match.params.name}
         /> )}
      />
    </Switch>
  );
}

We use the MatchProps interface that we created as the type for the props parameter in the render prop.

Then we can reference match.params as we wish.

Conclusion

We can make GraphQL queries in a React component with the React Apollo client.

React Router lets us pass in URL parameters easily.

It works with JavaScript and TypeScript.

We can prevent form submission with event.preventDefault() in the submit handler.