Categories
React Tips

React Tips — Disabling Links, Portals, and Pass Props to Components Passed in as Props

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.

How to Disable an <Link> if it’s Active

We can disable a link by setting the pointer-events attribute in our CSS.

Since we can pass a className attribute with the CSS class to the Link , we can write:

class Foo extends React.Component {
  render() {
    return (
      <Link to='/bar' className='disabled-link'>click me</Link>
    );
  }
}

We have the disabled-link class name applied to the link.

Then we can add the following CSS to disable the link:

.disabled-link {
  pointer-events: none;
}

How to Use ReactDOM.createPortal()

We can use the ReactDOM.createPortal() to render a component in an element outside of the usual location in the DOM tree,

For instance, given the following HTML:

<html>
  <body>
    <div id="root"></div>
    <div id="portal"></div>
  </body>
</html>

We can write:

const mainContainer = document.getElementById('root');
const portalContainer = document.getElementById('portal');

class Foo extends React.Component {
  render() {
     return (
       <h1>I am rendered through a Portal.</h1>
     );
  }
}

class App extends React.Component {
  render() {
    return (
      <div>
         <h1>Hello World</h1>
         {ReactDOM.createPortal(<Foo />, portalContainer)}
     </div>
    );
  }
}

ReactDOM.render(<App/>, mainContainer);

In App , we called ReactDOM.createPortal(<Foo />, portal to render the Foo component in the portalContainer , which is the div with ID portal in the HTML.

The rest of the JSX code is rendered in their usual places.

This lets us render our components in whatever way we like.

Event Bubbling Through Nested Components in React

React supports synthetic events in both the capturing and bubbling phases.

Therefore, our click events are propagated to the parent elements unless we stop them from doing so explicitly.

So if we have:

<root>
  <div onClick={this.handleAllClickEvents}>
    <foo>
      <bar>
        <target />
      </bar>
    </foo>
  </div>
</root>

We can listen to click events from child component with the handleAllClickEvents method.

Within it, we can write:

handleAllClickEvents(event) {
  const target = event.relatedTarget;
  const targetId = target.id;
  switch(targetId) {
    case 'foo':
      //...
    case 'bar':
      //...
  }
}

We get the click target with the event.relatedTarget property.

Then we get the click target’s ID with the id property.

Then we can check the IDs as we wish.

Difference Ways to Set the Initial State in a React Class Component

There’re multiple ways to set the initial state of a component in a class.

One way is standard and the other isn’t.

The standard way would be:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'james'
    }
  }

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

We set it in the constructor with the this.state assignment.

The non-standard way is:

class App extends Component {
  state = {
    name: 'John'
  }

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

This isn’t standard JavaScript syntax.

However, we can use it with TypeScript or a Babel plugin to transform it back to standard JavaScript.

This also sets the this.state instance variable.

Pass Props to a Component Passed as a Prop

If we want to pass props to a component that has been passed in as a prop, then we need to clone with the React.cloneElement method.

For instance, we can write:

const GrandChild = props => <div>{props.count}</div>;

class Child extends React.Component{
  constructor(){
    super();
    this.state = { count: 1 };
    this.updateCount= this.updateCount.bind(this);
  }

  updateCount(){
    this.setState(prevState => ({ count: prevState.count + 1 }))
  }

  render(){
    const Comp = this.props.comp;
    return (
      <div>
        {React.cloneElement(Comp, { count: this.state.count })}
        <button onClick={this.updateCount}>+</button>
      </div>
    );
  }
}

class Parent extends React.Component{
  render() {
    return(
      <Child comp={<GrandChild />} />
    )
  }
}

We have the GrandChild component which displays the count prop.

Then we have the Child prop to let us update the count state.

We pass that into the component that’s been passed in from the comp prop with React.cloneElement .

We got to clone it so that we return a version of the component that’s writable.

The 2nd argument has the prop name and value that we want to pass in respectively.

Conclusion

We can pass in props to a component that’s been passed in as a prop with the cloneElement method.

With portals, we can render our component anywhere we like.

And we can disable React Router links with CSS.

Categories
React Tips

React Tips — colspan, Active Links, API Calls, and Multiple Refs

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 API Call with Hooks in React

We can make API calls in the useEffect hook.

For instance, we can write:

function User() {
  const [firstName, setFirstName] = React.useState();

  React.useEffect(() => {
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        const {name} = data.results[0];
        setFirstName(name.first);
      });
  }, []);

  return (
    <div>
      Name: {firstName}
    </div>
  );
}

We get call fetch in the useEffect callback to get the data.

Then we set the firstNam,e state with setFirstName .

We pass in an empty array to the 2nd argument of useEffect to make the callback run on component mount only.

Finally, we render the firstName in the return statement.

If we want to load data when props change, then we pass the prop into the array in the 2nd argument.

React colspan

We can add the colspan attribute with the colSpan prop.

For instance, we can write:

<td colSpan={6} />

How can I Style Active Link in React Router

We can style an active link with React Router with the NavLink component.

For instance, we can write:

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

The activeClassName lets us set the class name for the when the link is active.

There’s also the activeStyle prop to let us pass in styles for active links.

For instance, we can write:

<NavLink
  to="/profile"
  activeStyle={{
    fontWeight: "bold",
    color: "green"
  }}
>
  profile
</NavLink>

We pass in an object with the styles we want to apply.

The CSS property names are all changed to camel case.

Trigger onChange if Input Value is Changing by State

We can set the state in the handler.

And we can trigger the event we want with the Event constructor.

For instance, we can write:

class App extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      value: 'foo'
    }
  }

  handleChange (e) {
    console.log('changed')
  }

  handleClick () {
    this.setState({ value: 'something' })
    const event = new Event('input', { bubbles: true });
    this.input.dispatchEvent(event);
  }
  render () {
    return (
      <div>
        <input readOnly value={this.state.value} onChange={(e) => this.handleChange(e)} ref={(input)=> this.input = input} />
        <button onClick={this.handleClick.bind(this)}>update input</button>
      </div>
    )
  }
}

We have a button that has a click handler attached to it.

That’s the handleClick method.

Then we call setState on it to set the value state.

We then create an input event and make it bubble.

Then trigger an event on the input with dispatchEvent .

Add Google Sign-in Button with React

We can add a Google sign-in button within a React component by loading the google sign-in code in when the component loads.

For instance, we can write:

componentDidMount() {
  gapi.signin2.render('g-signin2', {
    'scope': 'https://www.googleapis.com/auth/plus.login',
    'width': 200,
    'height': 50,
    'longtitle': true,
    'theme': 'dark',
    'onsuccess': this. onSignIn
  });
}

We call the gapi.signin2.render method that comes with the API.

It’s added to componentDidMount so that it runs when the component loads.

With function components, we can write:

useEffect(() => {
  window.gapi.signin2.render('g-signin2', {
    'scope': 'https://www.googleapis.com/auth/plus.login',
    'width': 200,
    'height': 50,
    'longtitle': true,
    'theme': 'dark',
    'onsuccess': onSignIn
  })
}, [])

We call the same method within the useEffect callback.

The empty array in the 2nd argument ensures that it loads only when the component loads.

Use Multiple refs for an Array of Elements with Hooks

We can create multiple refs within the useEffect callback.

For instance, we can write:

const List = ({ arr }) => {
  const arrLength = arr.length;
  const [elRefs, setElRefs] = React.useState([]);

  React.useEffect(() => {
    setElRefs(elRefs => (
      Array(arrLength).fill().map((_, i) => elRefs[i] || ReactcreateRef())
    ));
  }, [arrLength]);

  return (
    <div>
      {arr.map((el, i) => (
        <div ref={elRefs[i]}>...</div>
      ))}
    </div>
  );
}

We have the useState hook to create an array.

Then we call the setElRefs returned from useState to and call fill to create an array with empty slots.

Then we call map to create the refs or return an existing one.

Then we pass the ref by index to the div.

Conclusion

We can add multiple refs by mapping them to the array.

Also, we can make API calls in the useEffect callback.

NavLink s can be styled when they’re active.

Categories
React Tips

React Tips — Error Handling, Input Validation, and More

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.

Pass Props Without Value to Component

We can pass boolean props without a value to a component if its value is true .

For instance, we can write:

<input type="button" disabled />;

instead of:

<input type="button" disabled={true} />;

They’re the same.

Access Child Component Functions via Refs

We can assign a ref to a component in a class component to access its methods.

For instance, we can write:

class App extends React.Component {
  save() {
    this.refs.content.getWrappedInstance().save();
  }

  render() {
    return (
      <Dialog action={this.save.bind(this)}>
        <Content ref="content"/>
      </Dialog>);
   }
}

class Content extends React.Component {
  save() {
    //...
  }
}

We have the App component that has the Content that has a ref assigned to it.

Then we can get the component instance with getWrapperdInstance .

And we can call the save method with that.

getDerivedStateFromError and componentDidCatch

Both are methods that let us handle errors in a class component.

getDerivedStateFromError is a static method that lets us set a state when an error occurs.

componentDidCatch lets us commit side effects and access this , which is the component instance.

For instance, we can write:

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    console.log(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <h1>error.</h1>;
    }

    return this.props.children;
  }
}

We have the static getDerivedStateFromError method to access the error parameter.

Then we can return something which is the state that’s rendered with the next render.

componentDidCatch lets us access the component instance.

It also has the error and info parameters with more error data.

getDerivedStateFromError works with server-side rendering.

This is because it’s a render phase lifecycle, which is available on server-side rendered apps.

Allow File Input to Select the Same File in React Component

We can let a file input select the same file in a React component if we set it to null after we click on it.

For instance, we can write:

<input
  id="upload"
  ref="upload"
  type="file"
  accept="image/*"
  onChange={(event)=> {
    this.readFile(event)
  }}
  onClick={(event)=> {
    event.target.value = null
  }}
/>

We have the onChange prop that takes a function to read a file.

In the onClick prop, we set the file input value to null .

Passing a Number to a Component

We can pass a number to a component by passing in a number in curly brackets.

For instance, we can write:

Rectangle width={10} height={20} />

Using the Same Component for Different Route path in React Router

We can use the same component for different routes by passing in an array into the path prop.

So we can write:

<Route exact path={["/add", "/edit"]}>
  <User />
</Route>

Conditional Validation in Yup

We can validate a field conditionality with Yup by using the when method.

For instance, we can write:

validationSchema={yup.object().shape({
  showName: yup.boolean(),
  name: yup
    .string()
    .when("showName", {
      is: true,
      then: yup.string().required("name is required")
    })
  })
}

We have the showName boolean field.

And we only validate the name field when it’s true as indicated in the is field.

then lets us do the validation only when showName is true .

Then we return the 'name is required' message if it is.

Fix ‘ Failed form propType: You provided a checked prop to a form field without an onChange handler.’ Warning

To fix this warning, we can add the checked prop with a value if we’re creating a controller component.

For instance, we can write:

<input
  type="checkbox"
  checked={this.props.checked}
  onChange={this.onChange}
/>

If it’s an uncontrolled component, we can write populate the defaultChecked prop:

<input
  type="checkbox"
  defaultChecked={this.props.checked}
/>

Only Allow Numbers to be Inputted in React

We can set the pattern attribute to the regex string we want for restricting the input to numbers.

For instance, we can write:

<input type="text" pattern="[0-9]*" onInput={this.handleChange.bind(this)} value={this.state.goal} />

We specified the pattern and we listen to the inpurt pro.

Then in the handleChange method, we can write:

handleChange(evt) {
  const goal = (evt.target.validity.valid) ?
  evt.target.value : this.state.goal;
  this.setState({ goal });
}

We only set the state if it’s valid, then we won’t get any invalid input in the state.

Conclusion

We can check for input validity in the input handler.

Also, we don’t have to pass in true explicitly into a prop.

Error boundary components have special hooks that we can run code when errors occur.

Categories
React Tips

React Tips — Value Changes, Server/Client-Side Rendering

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.

Why Can’t Input Value be Changed in React

We can’t change input value with React because we’ve to set the value prop of the input manually.

For instance, we write:

<input
  className="form-control"
  type="text"
  value={this.state.name}
  onChange={e => this.onChange(e.target.value)}
/>

Then in the onChange method, we can write:

onChange(value){
  this.setState({
     name: value
  });
}

We set the name state in the method.

How to Render Text with a Single Quote with React JSX

We can render a string to render single quotes.

For instance, we can write:

return (
   <div>
     <p>{"I've eaten."}</p>
   </div>
 )

We can also use the HTML entity version of the single quote.

For instance, we can write:

<Text>I&quot;ve eaten.</Text>

Check if Variable is React Node or Array

We can use React.isValidElement to check if a variable is a node or an array.

It takes a variable to check.

And it returns true if it is and false otherwise.

Detect if a Component is Rendering from the Client or the Server

We can use lifecycle hooks to detect server-side rendering.

If they run, then it’s rendered on the client-side.

Therefore, we can create our own hook to do the check.

We write:

import { useState, useEffect } from 'react'

function useIsClient () {
  const [isClient, setIsClient] = useState(false)
  useEffect(() => {
    setIsClient(true)
  }, [])
  return setIsClient
}

to create the useIsClient hook.

If the useEffect callback is run, then we know that it’s rendered on the client-side.

Then we can check that it’s a client-side rendered app.

Then we can use it by writing:”

import { useState, useEffect } from 'react'

function useIsClient () {
  const [isClient, setIsClient] = useState(false)
  useEffect(() => {
    setIsClient(true)
  }, [])
  return setIsClient
}

function App() {
  const isClient = useIsClient();
  return isClient
    ? 'client'
    : 'serve'
}

We use the useIsClient hook to check for client-side rendering.

Then we can render what we want according to that.

Change Checkbox State

We can change the checkbox state by passing in the checked prop to the checkbox.

For instance, we can write:

class CheckBox extends React.Component {
  render() {
    return (<input type="checkbox" checked={this.props.checked} />);
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { checked: true };
  }

  render() {
    return (
      <div>
        <a href="#" onClick={ () => { this.setState({ checked: !this.state.checked }); }}>Toggle</a>
        <hr />
        <CheckBox checked={this.state.checked} />
      </div>
    );
  }
}

We toggle the checkbox when we click on the link.

Then we pass in the checked state to our CheckBox component, which has the checkbox.

Then in the CheckBox component, we pass the checked prop to the checked value.

Use Normal Anchor Links with React Router

The React Router Hash Link package lets us create hash links easily in our React app if we use React Router.

To install it, we run:

yarn add react-router-hash-link

or:

npm install --save react-router-hash-link

Then we can use it by writing:

import { HashLink as Link } from 'react-router-hash-link';

//...
const App = () => {
  //...
  return <Link to="/some/path#some-hash">hash link</Link>
}

We can also add a nav link, which lets us set the active style.

We can use that by writing:

import { NavHashLink as NavLink } from 'react-router-hash-link';

//...
const App = () => {
  //...
  return <NavLink
    to="/some/path#some-hash"
    activeClassName="acrive"
  >
     hash nav link
  </NavLink>
}

It takes an activeClassName prop to let us set the active class name when the link is active.

Also, it supports changing the scroll behavior when we navigate to the element with the given ID.

The link can also be customized.

Conclusion

We can use a package to create our hash links if our app uses the React Router.

Input changes can be displayed if we set the value prop for text inputs.

For checkbox inputs, we can pass in a value to the checked prop.

We can render single quotes as an HTML entity or in a string.

Categories
React Tips

React Tips — Pseudo-Elements, Conditional Display and Constructor

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.

Conditionally Displaying Items in a React Component

We can conditionally display items in a React component in various ways.

One way is to use a ternary expression.

For instance, we can write:

render() {
  return (
    this.props.showMe ? <button type="submit">show me</button> : null
  );
}

The first item is shown if showMe is true and null is rendered otherwise.

We can also use the && operator.

For instance, we can write;

`{`showMe `&&` <button type="submit">show me</button>`}`

Is showMe is true then the button is rendered since the expression will be evaluated.

CSS Pseudo-elements in React

We can add prefixed styled by adding them as properties of the style object.

For instance, we can write:

render() {
  return (
    <div>
      <span>Something</span>
      <div style={{ WebkitFilter: 'blur(10px) saturate(2)' }} />
      </div>
  );
},

We have the WebkitFilter property which is equivalent to CSS’s -webkite-filter property.

To make our lives raise,r we can use the style-it package to convert any CSS property to JavaScript style properties.

To install it, we run:

npm install style-it --save

Then we can use it by writing:

import React from "react";
import Style from "style-it";
class Intro extends React.Component {
  render() {
    return Style.it(
      `
        .tooltip {
          display:inline-block;
          position:relative;
          border-bottom:1px dotted #666;
          text-align:left;
        }
        .tooltip .right {
          min-width:200px;
          top:50%;
          left:100%;
          margin-left:20px;
          transform:translate(0, -50%);
          padding:10px 20px;
          color:#444444;
          background-color:#EEEEEE;
          font-weight:normal;
          font-size:13px;
          border-radius:8px;
          position:absolute;
          z-index:99999999;
          box-sizing:border-box;
          box-shadow:0 1px 8px rgba(0,0,0,0.5);
          display:none;
        }
        .tooltip:hover .right {
          display:block;
        }
        .tooltip .right i {
          position:absolute;
          top:50%;
          right:100%;
          margin-top:-12px;
          width:12px;
          height:24px;
          overflow:hidden;
        }
        .tooltip .right i::after {
          content:'';
          position:absolute;
          width:12px;
          height:12px;
          left:0;
          top:50%;
          transform:translate(50%,-50%) rotate(-45deg);
          background-color:#EEEEEE;
          box-shadow:0 1px 8px rgba(0,0,0,0.5);
        }
    `,
      <div id="tooltip" />
    );
  }
}

We use the Style component with the CSS embedded in the string.

Then anything that comes after the string will be styled with the given styles.

Also, we can use the styled-components library to do the same thing.

We can install it by running:

npm i styled-components

Then we can write:

import React from 'react';
import styled from 'styled-components';

const Tooltip = styled.div`
  .tooltip {
    display:inline-block;
    position:relative;
    border-bottom:1px dotted #666;
    text-align:left;
  }
  .tooltip .right {
    min-width:200px;
    top:50%;
    left:100%;
    margin-left:20px;
    transform:translate(0, -50%);
    padding:10px 20px;
    color:#444444;
    background-color:#EEEEEE;
    font-weight:normal;
    font-size:13px;
    border-radius:8px;
    position:absolute;
    z-index:99999999;
    box-sizing:border-box;
    box-shadow:0 1px 8px rgba(0,0,0,0.5);
    display:none;
  }
  .tooltip:hover .right {
    display:block;
  }
  .tooltip .right i {
    position:absolute;
    top:50%;
    right:100%;
    margin-top:-12px;
    width:12px;
    height:24px;
    overflow:hidden;
  }
  .tooltip .right i::after {
    content:'';
    position:absolute;
    width:12px;
    height:12px;
    left:0;
    top:50%;
    transform:translate(50%,-50%) rotate(-45deg);
    background-color:#EEEEEE;
    box-shadow:0 1px 8px rgba(0,0,0,0.5);
  }
}
`;

const App = () => {
  return (
    <Tooltip>...</Tooltip>
  )
}

We used the styled.div template tag, which is a function that takes CSS styles and returns a component with the styles.

Then we can use them in our component as we did in App .

Functions in Stateless Components

We can call functions that are outside of the component within the component.

For instance, we can write:

const App = props => (
  <Something onClick={props.update} />
);

We can get functions from props and call them.

We can also have functions inside the component.

For instance, we can write:

const App  = props => {
  const onClick = useCallback((a, b) => {
    //...
  }, [props.x]);

  return (
    <Something onClick={onClick} />
  );
}

We use the useCallback gook to ensure that functions are only redefined when one of the dependencies in the array changes.

Calling super() in a React Component Constructor

We call super inside the constructor if we have to use this.props .

For instance, we writ:

class App extends React.component{
  constructor(props){
    super(props);
    console.log(this.props);
  }
}

So that we get access to this.props in our component’s code.

Subclasses must call super before referencing this either simplicity or explicitly.

Conclusion

We can use libraries to incorporate pseudo-classes in our React component code.

Also, we’ve to call super before using this in class components.

Items can be conditionally displayed with boolean expressions.