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.

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.