Categories
React Tips

React Tips — Restricted Routes, Booleans, Wrapping, and Select Values

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.

Restrict Access to Routes in React Router

We can restrict access to routes by checking for credentials.

Then we can return the component if the credentials are valid.

Otherwise, we redirect to the path that we want to redirect to.

For instance, we can write:

export default function AuthenticatedRoute({ component: Component, appProps, ...rest }) {
  return (
    <Route
      {...rest}
      render={props =>
        appProps.isAuthenticated
          ? <Component {...props} {...appProps} />
          : <Redirect
              to={`/login?redirect=${props.location.pathname}${props.location.search}`}
            />}
    />
  );
}

export default function App() {
  const [authenticated, setAuthenticated] = useState(false);

  useEffect(() => {
    onLoad();
  }, []);

  async function onLoad() {
    try {
      await getSession();
      setAuthenticated(true);
    } catch (e) {
      console.log(e);
    }
  }

  return (
    <div>
      <Switch>
        <AuthenticatedRoute
          path="/profile"
          component={Profile}
          appProps={{ authenticated }}
        />
        <Route component={Login} path="/login" />
      </Switch>
    </div>
  );
}

We created the AuthenticatedRoute that takes the component we want to restrict.

We check for the credentials in the component.

Then if it’s valid, we return the component to render it.

Otherwise, we return the Redirect component to redirect to the login route.

Toggle Boolean State of React Component

We can toggle the boolean state of a React component by calling setState with the opposite value of the state that we have now.

For instance, we can write:

class A extends React.Component {
  constructor() {
    super()
    this.handleCheckBox = this.handleCheckBox.bind(this)
    this.state = {
      checked: false
    }
  }

  handleCheckBox(e) {
    this.setState({
      checked: e.target.checked
    })
  }

  render(){
    return <input type="checkbox" onChange={this.handleCheckBox} checked={this.state.checked} />
  }
}

We have a checkbox that we passed the this.handleCheckBox method to update the checked state.

Then we update the state by calling setState in there.

Then we set the checked prop to the this.state.checked state.

With function components, we can write:

import React from "react";

function App(props) {
  const [toggled, setToggled] = React.useState(false);

  return  (
    <button
      onClick={(event) => {
       setToggled(!toggled);
     }}
    >
      {toggled.toString()}
    </button>;
}

We set the toggled state when we click the button to the opposite of the existing value of the toggled state.

Then we see what we have by setting the string as version of toggled as the content of the button.

Default Export of a Component

To export a component as a default export, we can write:

const Header = () => {
  return <p>hello</p>
};
export default Header;

or:

export default () => (
  <p>hello</p>
)

We define our const variable separately and then we export it.

Or we export the component directly.

Conditionally Wrap a React component

To conditionally wrap a React component, we can create a higher-order component to do the conditional wrapping.

For instance, we can write:

const WithLink = ({ link, className, children }) => (link ?
  <a href={link} className={className}>
    {children}
  </a>
  : children
);

const Link = ({ link, className, count }) => {
  return (
    <WithLink link={link} className={className}>
      <i className={styles.Icon}>
        {count}
      </i>
    </WithLink>
  );
}

We created a WithLink higher-order component to get the link and then use that to check if we should put a wrapper around our component.

Then in our Link component, we get the link and className props and pass them into the WithLink component.

We pass the count prop into the icon class.

Get Values from a <select> Element with Multiple Option in React

We can create a component with the select element that can accept multiple selections.

Then we can add an onChange handler to get the options from the select element.

For instance, we can write:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      multiValue: []
    }
  }

  handleChange(e) {
    this.setState({ multiValue: [...evt.target.selectedOptions].map(o => o.value) });
  }

  render() {
    return (
      <select multiple value={this.state.multiValue} onChange={this.handleChange}>
        <option value='apple'>Apple</option>
        <option value='orange'>Orange</option>
        <option value='grape'>Grape</option>
      </select>
    );
  }
}

We get all the selected options with the evt.target.selectedOptions property.

Then we map each entry to their value by returning the value property.

Conclusion

We can get all the selected values of the multiple select elements with the evt.target.selectedOptions.

Also, we can create restricted routes with React Router.

And we can toggle a boolean state when we do something to a React component.

Categories
React Tips

React Tips — Input Event, Redux, Forward Ref and Bubbling

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.

Best Way to Trigger Change Event in React

We can trigger events programmatically by getting the native input value setter.

Then we can trigger the input event with it instead of React’s version.

For instance, we can write:

const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, 'something');

const ev = new Event('input', { bubbles: true });
input.dispatchEvent(ev);

We get the native input value setter with:

const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;

Then we create a native input event by writing:

nativeInputValueSetter.call(input, 'something');

The first argument is the input element.

The 2nd is the value of the input.

Then we created the event with:

const ev = new Event('input', { bubbles: true });

And then we dispatch the input event on the input element with:

input.dispatchEvent(ev);

Prevent Event Bubbling in Nested Components on Click

We can prevent event bubbling in nested components on click by using the stopProphation method.

For instance, we can write:

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

  handleClick(e) {
    e.stopPropagation();
    this.props.onClick();
  }

  render() {
    return (
      <li onClick={this.handleClick}>
        {this.props.children}
      </li>
    )
  }
}

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

  handleClick(e) {
    // ...
  }
  render() {
    return (
      <ul onClick={this.handleClick}>
        <ListItem onClick={this.handleClick}>Item</ListItem>
      </ul>
    )
  }
}

Since we have a click listen for the ul element and multiple click listeners for the li elements, we’ve to call stopPropagation on the li elements’ click handlers so that the click event won’t bubble up to the ul element and beyond.

We did that with:

e.stopPropagation();

in the handleClick method of ListItem .

Use React.forwardRef in a Class-Based Component

We can use React.forwardRef in a class-based component by passing in a callback that returns the class-based component inside.

For instance, we can write:

class DivComponent extends Component {
  render() {
    return (
      <div ref={this.props.innerRef}>
        foo
      </div>
    )
  }
}

const Comp = React.forwardRef((props, ref) => <DivComponent
  innerRef={ref} {...props}
/>);

We pass in a callback with the props and ref parameters and we return the DivComponent with the props and ref passed in as props of it.

Then we can access the ref by referencing the this.props.innerRef so that we can assign it as the ref of the div.

Simple Dispatch from this.props Using connect with Redux

We can map our dispatch functions to props by using the mapDispatchToProps method.

For instance,e we can write:

const mapDispatchToProps = (dispatch) => {
  return {
    onClick: () => dispatch(decrement())
  };
}

to map the dispatch call for the decrement action to the onClick prop.

We can also put the dispatch function into the object to access it directly:

function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onClick: () => dispatch(decrement())
  };
}

We can also use bindActionCreators to turn:

function mapDispatchToProps(dispatch) {
  return {
    onPlusClick: () => dispatch(increment()),
    onMinusClick: () => dispatch(decrement())
  };
}

to:

import { bindActionCreators } from 'redux';

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    onPlusClick: increment,
    onMinusClick: decrement
  }, dispatch);
}

We mapped the increment and decrement actions to the onPlusClick and onMinusClick props.

And we can shorten that to:

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({ increment, decrement }, dispatch);
}

Then we just get the increment and decrement from the props and call them to dispatch the actions.

We can shorten it even more by turning:

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({ increment, decrement }, dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

Into:

export default connect(
  mapStateToProps,
  { increment, decrement }
)(App);

This will inject increment and decrement as props without mapDispatchToProps .

Update Single Value Inside Specific Array Item in Redux

We can update a single value inside a specific array item in Redux writing our reducer in a way that divides the array, modifies the entry we want to change, and join them back together.

For instance, we can write:

case 'MODIFY_ARRAY':
   return {
       ...state,
       contents: [
          ...state.contents.slice(0, index),
          { title: "title", text: "text" },
         ...state.contents.slice(index + 1)
       ]
    }

We called slice to divide the array into chunks. Then we have our next object between the chunks.

Then we use the speed operator to join them back together into one array.

Conclusion

There are many shorthands for mapDispatchToProps .

We can change an array entry by returning a new array in a reducer.

We can call stopPropagation to stop event bubbling.

Also, we can trigger an input event programmatically with the native input value setter.

Categories
React Tips

React Tips — Redux States, Dynamic Elements, and Pretty Print JSON

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.

Access Store State in React Redux

We can access store state in React Redux with the mapStateProps method.

For instance, we can write:

import React from "react";
import { connect } from "react-redux";

const App = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
    </div>
  );
}

const mapStateToProps = state => {
  return {
    name: state.name
  };
};
export default connect(mapStateToProps)(App);

We call connect with mapStateToProps to add the Redux store states as props of the App component.

Then we can just get it with props.name as we did in App .

Render Repeating React Elements

We can render repeating React elements with the map method.

For instance, we can write:

{this.props.titles.map(title =>
  <div key={title}>{title}</div>
)}

We have the titles prop and call map to return a div from each title entry.

We cal also use the Array.from method to make an array from something that’s not an array.

For instance, we can write:

<div>
  { Array.from({ length: 3 }, (value, index) => <div key={value.id}>}{value.name}</div>) }
</div>

We called Array.from create an empty array with length of 3, then we map the empty slots to an element.

There’s also the Array.fill method to render the elements from empty array slots:

<div>
 { Array(3).fill(<div />) }
</div>

Toggle Class when Clicked in a React Component

We can set a state to let us toggle a class when we click something in a React component.

For instance, we can write:

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

  toggleClass() {
    const currentState = this.state.active;
    this.setState({ active: !currentState });
  };

  render() {
    return (
      <div
        className={this.state.active ? 'active': null}
        onClick={this.toggleClass}
      >
        <p>hello</p>
      </div>
    )
  }
}

We have the toggleClass method which is called when we click on the div.

In the method, we set the active state to the opposite of the current value.

Then we get the class name depending of the value of this.state.active .

Dynamically Add Child Components in React

To dynamically add child components to React, we can change the state, and then we can render what we want based on the state.

For instance, we can write:

class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      data: [
        { id: 1, name: "foo" }
      ]
    }
    this.addChild = this.addChild.bind(this);
  }

  addChild() {
    const newData = { id: 2, name: "bar" };
    this.setState(state => [...state.data, newData])
  }

  render() {
    return (
      <div>
         <button onClick={this.addChild}>Add name</button>
         {this.state.data.map((item) => (
            <div key={item.id}>{item.name></div>
         )}
      </div>
    );
  }
}

We have the addChild method which calls setState to set the new value of data by passing in a callback to append the new entry to the data state.

Then in the render method, we map the data state to an entry in by calling array instance’s map method.

We return a component or element we want to display.

Pretty Printing JSON with React

We can pretty print JSON with React with the pre element.

For instance, we can write:

class PrettyPrintJson extends React.Component {
  render() {
    const { data }= this.props;
    return (<div><pre>{JSON.stringify(data, null, 2) }</pre></div>);
  }
}

We called JSON.stringify with 2 as the 3rd argument to indent the data that we display as the data.

With a function component, we can write:

const PrettyPrintJson = ({data}) => (
  <div>
    <pre>
      {JSON.stringify(data, null, 2)}
    </pre>
  </div>
);

We just return the JSX expression for pretty print directly.

Also, we can cache the JSON data with React.memo .

For example, we can write:

const PrettyPrintJson = React.memo(
  {data}) => (
    <div>
      <pre>
        {JSON.stringify(data, null, 2)}
      </pre>
    </div>
  )
);

Conclusion

We can render repeated elements by using array methods to map data to JSX expressions.

Also, we can pretty-print JSON by using JSON.stringify to pretty print our JSON with indentation.

We can toggle classes and render elements dynamically by changing states and then rendering whatever we want with the render method.

Finally, we can use mapStateToProps to map Redux states to props.

Categories
React Tips

React Tips — Event Handlers, componentDidUpdate, and Height of an Element

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.

Get Height of an Element

We can get the height of an element by assign a ref to an element and then use the clientHeight property to get the height of it.

For instance, we can write:

import React, {Component} from 'react'

class DivSize extends Component {

  constructor(props) {
    super(props)

    this.state = {
      height: 0
    }
  }

  componentDidMount() {
    const height = this.divElement.clientHeight;
    this.setState({ height });
  }

  render() {
    return (
      <div
        className="test"
        ref={(divElement) => { this.divElement = divElement }}
      >
        Size: <b>{this.state.height}px</b>
      </div>
    )
  }
}

We assigned a ref to the div element by writing:

ref={(divElement) => { this.divElement = divElement }}

Then in the componentDidMount hook, we can the div’s height with the clientHeight property.

Then we call setState to set the height state.

With function components, we can do the same thing.

For instance, we can write:

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

export default () => {
  const [height, setHeight] = useState(0)
  const ref = useRef(null)

  useEffect(() => {
    setHeight(ref.current.clientHeight)
  }, [])

  return (
    <div ref={ref}>
      {height}
    </div>
  )
}

We create a ref and assign it to the div.

The ref is created with the useRef hook.

We also call useState to create a state for the height and a function to set it.

Then in the useEffect callback, we can call the setHeight function with the ref.current.clientHeight to set the value of height state to the div’s height.

Then we display the height in the div.

Using this.props.children for Displaying Child Components

We can use this.props.children to display child components.

For instance, we can write:

class Parent extends React.Component {
  render() {
    return <div>
      <div>Children ({this.props.children.length}):</div>
      {this.props.children}
    </div>;
  }
}

class App extends React.Component {
  render() {
    return <div>
      <div>first example</div>
      <Parent>
        <div>1</div>
        <div>2</div>
        <div>3</div>
      </Parent>
      <div>second example</div>
      <Parent>
        <div>A</div>
        <div>B</div>
      </Parent>
    </div>;
  }
}

We created a Parent component that rendered the children prop.

Then in the App component, we used the Parent component.

And then we pass in the divs that we want to display as the children of Parent .

And they’ll be displayed.

this.props.children is an array, so we can display the length of the children prop.

Call Multiple Functions onClick in React

We can call multiple functions in our click handler.

For instance, we can write:

class App extends React.Component {
   onClick(event) {
      func1();
      func2();
   }
   render() {
      return (
         <button onClick={this.onClick}>click me</button>
      );
   }
}

We have the onClick method that calls multiple functions.

If we want to do that inline, we can write:

class App extends React.Component {
   render() {
      return (
         <button onClick={() => { func1(); func2(); }}>click me</button>
      );
   }
}

Uses for the React “componentDidUpdate” Method

We can use the componentDidUpdate method to watch for changes in our state values and then run code when they change.

For instance, we can write:

class Form extends React.Component {

  constructor(props, context) {
    super(props, context);
    this.state = {
      firstName: "",
      lastName: "",
      age: ""
    };
    this.changeFirstName = this.changeFirstName.bind(this);
    this.changeLastName = this.changeLastName.bind(this);
    this.changeAge = this.changeAge.bind(this);
  }

  componentDidUpdate() {
    this.autoSave();
  }

  changeFirstName(e){
    this.setState({ firstName: e.target.value });
  }

  changeAge(e){
    this.setState({ age: e.target.value });
  }

  changeLastName(e) {
    this.setState({ lastName: e.target.value });
  }

  autoSave() {
    const { firstName, lastName, age } = this.state;
    post('/autosave', {
      firstName,
      lastName,
      age
    });
  }

  render() {
    const { firstName, lastName, age } = this.state;
    return (
      <form>
        <input type="text" value={firstName} onChange={this.changeFirstName} />
        <input type="text" value={lastName} onChange={this.changeLastName} />
        <input type="text" value={age} onChange={this.changeAge} />
      </form>
    );
  }
}

We have 3 inputs with 3 change handlers to update each of their inputted values as the new state values.

Once that happens, the componentDidUpdate will run and the POST request will be made.

It’ll run after the DOM is updated and the update queue is emptied.

Conclusion

componentDidUpdate is useful for running updates when the state updates.

We can get the height of an element by assigning a ref and using the clientHeight property on it.

We can call whatever we want in our event handlers.

Categories
React Tips

React Tips — Hooks Equivalents to Class Lifecycle Methods, Dynamic Tags

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.

Reference a Local Image in React

We can reference a local image with React by loading it as a module.

For instance, we can write:

<img src={require('./pic.jpeg')} />

or:

import pic from './pic.jpeg';

//...

`<img src={`pic`} />`

or:

const pic = require('./pic.jpeg');

//...

<img src={pic} />

Images can be loaded as modules with Webpack.

Scroll to the Top of the Page After Render

We can scroll to the top of the page after render by writing;

componentDidMount() {
  window.scrollTo(0, 0)
}

in a class component.

componentDidMount runs code when the component mounts.

window.scrollTo(0, 0) scrolls to the top of the page.

In a function component, we can write:

useEffect(() => {
  window.scrollTo(0, 0)
}, [])

to scroll to the top of the page.

useEffect with an empty array as the 2nd argument only runs when the component is mounted.

Why are Fragments in React Better than Container divs?

Fragments are a bit faster and has less memory usage since no extra DOM node is created.

Some CSS features like flexbox and grid have their own special parent-child relationship, so add a wrapper div will interfere with those layouts.

And less DOM elements means that there’re fewer elements to inspect.

We can make our code cleaner with:

render() {
  return (
    <>
      foo.
      <h2>A heading</h2>
      bar.
      <h2>heading</h2>
      baz.
    </>
  );
}

or:

render() {
  return (
    <React.Fragment>
      foo.
      <h2>A heading</h2>
      bar.
      <h2>heading</h2>
      baz.
    </React.Fragment>
  );
}

If we need to add the key prop, then we’ve to use the long-form.

Set Default Checked Value in Checkbox with React

We can set the default checked value in a checkbox with React by using the checked attribute.

For instance, we can write:

function Checkbox() {
  const [checked, setChecked] = React.useState(true);

  return (
    <label>
      <input type="checkbox"
        checked={checked}
        onChange={() => setChecked(!checked)}
      />
      check me
    </label>
  );
}

We called the useState hook with to set the initial value of the checked state.

And we use the setChecked function to set the checked state as we get the checked value.

onChange runs every time we check or uncheck a button, so we can pass a callback to that set the latest checked state.

With class components, we write:

class Checkbox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      checked: true,
    };
  }
  toggleChange = () => {
    this.setState({
      checked: !this.state.checked,
    });
  }
  render() {
    return (
      <label>
        <input type="checkbox"
          checked={this.state.checked}
          onChange={this.toggleChange}
        />
        check me
      </label>
    );
  }
}

We have a checkbox that also have the checked and onChange props set.

However, in the toggleChange method, we called setState to update the state instead of calling a state change function.

Use componentDidMount() in React Hooks

If we use React hooks, then we can’t use any of the component lifecycle hooks that are in class components.

Instead, we’ve to find their hooks equivalent.

The hooks equivalent of componentDidMount is the useEffect hook with an empty array as its 2nd argument.

For instance, instead of writing:

componentDidMount() {
  window.addEventListener('click', () => {})
}

componentWillUnmount() {
  window.removeEventListener('click', () => {})
}

in a class component.

We write:

useEffect(() => {
  window.addEventListener('click', () => {});

  return () => {
    window.removeEventListener('click', () => {})
  }
}, [])

componentDidMount is equivalent to the useEffect hook with an empty array.

And componentWillUnmount is equivalent to the callback we return in the useEffect callback.

Dynamic Tag Name in JSX and React

If we want to create an element with a dynamic tag name with React, we can use the React.createElement method.

For instance, we can write:

React.createElement(`h${this.props.level}`, null, 'Hello')

In a component, we can write:

import React from 'react';

function Heading({ level, children, ...props }) {
  return React.createElement(`h${level}`, null, children)
}

Heading.defaultProps = {
  level: '1',
};

We pass in the level prop to set the type of heading.

children has the content.

Then we can use it by writing:

<Heading level="1">foo bar</Heading>

Conclusion

We can use createElement to create elements with dynamic tags.

Also, we can reference local images with React.

Fragments are better than wrapper divs since they don’t render any extra elements.

There are hooks equivalents of class component lifecycle methods.