Categories
React Tips

React Tips — Disable Buttons, FormData, Types for Function

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.

Send Multipart Form Data with Axios in a React Component

We can send form data with the FormData constructor.

We can pass that straight into the Axios post method.

For instance, we can write:

import React from 'react'
import axios, { post } from 'axios';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state ={
      file:null
    }
    this.onFormSubmit = this.onFormSubmit.bind(this)
    this.onChange = this.onChange.bind(this)
    this.fileUpload = this.fileUpload.bind(this)
  }

  onFormSubmit(e){
    e.preventDefault()
    const url = 'http://example.com/upload';
    const formData = new FormData();
    formData.append('file', this.state.file);
    const config = {
      headers: {
        'content-type': 'multipart/form-data'
      }
    }
    post(url, formData, config);
      .then((response) => {
        console.log(response.data);
      })
  }

  onChange(e) {
    this.setState({ file: e.target.files[0 ]})
  }

  render() {
    return (
      <form onSubmit={this.onFormSubmit}>
        <h1>File Upload</h1>
        <input type="file" onChange={this.onChange} />
        <button type="submit">Upload</button>
      </form>
   )
  }
}

We have a file input, where we set the file input to the file that’s submitted in the onChange method.

We save the selected file object as the value of the file state.

Then when we click the Upload button, onFormSubmit is run.

In the method, we created a FomrData instance.

Then we append our file into the FormData instance.

We also set the header so that we indicate that we’re sending form data.

Once we did that, we proceed with our file upload.

Disable Button with React

We can disable a button with React by setting the disabled prop of the button.

For instance, we can write:

<button disabled={!this.state.value} />

We can use it in a component by writing:

class ItemForm extends React.Component {
  constructor() {
    super();
    this.state = { value: '' };
    this.onChange = this.onChange.bind(this);
    this.add = this.add.bind(this);
  }

  add() {
    this.props.addItem(this.state.value);
    this.setState({ value: '' });
  }

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

  render() {
    return (
      <div>
        <input
          type="text"
          value={this.state.value}
          onChange={this.onChange}
          placeholder='item name'
        />
        <button
          disabled={!this.state.value}
          onClick={this.add}
        >
          Add
        </button>
      </div>
    );
  }

We pass in the value state to let us enter the data that we want into the input field.

Then we check that in disabled prop of the button.

This way, the button is disabled if we have nothing inputted into the form field.

Cannot Read Property ‘map’ of Undefined

We may get this if we try to call map on something that doesn’t have a map method.

This may happen to something that we expect to be an array, but it’s not.

Therefore, we should check if the value we’re calling map on is an array before doing anything.

For instance, we can do that by writing:

if (Array.isArray(this.props.data)) {
  const commentNodes = this.props.data.map((comment) => {
    return (
      <div>
        <h1>{comment.title}</h1>
      </div>
    );
  });
}

We called Array.isArray to check if this.props.data is an array.

If it is, then we call map to map the data prop to h1 elements.

How to Add Custom HTML Attributes in JSX

With React 16, we can add custom attributes natively.

For instance, we can write:

render() {
  return (
    <div data-foo="bar" />
  );
}

We can just add it straight into our HTML elements without doing anything special.

Use Children with React Stateless Functional Component in TypeScript

We can pass in the interface or type alias into the generic type argument of React.FunctionComponent to set the type for ur props.

As long as the alias or interface has the children prop, we can use the children prop.

For instance, we can write:

const Foo: React.FunctionComponent<FooProps> = props => (
  <div>
    <p>{props.bar}</p>
    <p>{props.children}</p>
  </div>
);

FooProps has the bar and children entries, so we can reference both in our component.

React.FC is the shorthand for React.FunctionComponent .

Before React 16.8, we use the React.StatelessComponent type instead.

For instance, we can write:

const Foo: React.StatelessComponent<{}> = props => (
  <div>{props.children}</div>
);

or:

const Foo : React.StatelessComponent<FooProps> = props => (
  <div>
    <p>{props.propInMyProps}</p>
    <p>{props.children}</p>
  </div>
);

React.SFC is the shorthand for React.StatelessComponent.

Conclusion

We can add types to stateless components with TypeScript.

Sending multipart form data can be done with the FormData constructor.

Also, we should make sure that we have an array before calling map on it.

We can conditionally disable buttons with React.

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 — 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.

Categories
React Tips

React Tips — Basic Hooks

React is one of the most popular libraries for creating front end apps. It can also be used to create mobile apps with React Native.

In this article, we’ll look at some basic hooks that are built-into React to make our function components smart.

State and useState

We can use the useState hook to store the state of our app. Therefore, it’s a basic building block of a smart React function component.

To use it, we write the following code:

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0);

  return (
    <>
      <button onClick={() => setCount(count => count - 1)}>decrement</button>
      <p>{count}</p>
    </>
  );
}

In the code above, we have the count state returned as the first element of the array returned by the useState hook.

We then defined an onClick handler which calls the setCount function returned as the 2nd element in the array returned by useState .

In there, we updated the count by returning the existing count value minus 1.

This lets us modify a state’s value based on its previous value. We can also pass in whatever we want to set directly if it doesn’t depend on the previous value of a state.

Passing in a callback will guarantee that the update is done based on the previous value of the state.

For instance, we can pass in a value directly into the state change function as follows:

import React from "react";

export default function App() {
  const [text, setText] = React.useState("foo");

  return (
    <>
      <button onClick={() => setText("foo")}>foo</button>
      <button onClick={() => setText("bar")}>bar</button>
      <button onClick={() => setText("baz")}>baz</button>
      <p>{text}</p>
    </>
  );
}

In the code above, we have 3 buttons that have click handlers that call setText to set the value of the text state.

Since the value we set doesn’t depend on the previous value, we can just set it directly by passing in the value that we want to set the value of text to.

The state change function can be used more than once, as we can see from the previous example.

It can accept any kind of value, including primitive values and objects.

Side effects and useEffect

The React useEffect hook is another important hook that we can’t overlook.

It’s used to commit side effects like updating data asynchronously from an API or working with the DOM.

Side effects are actions that can change our component in an unpredictable fashion.

It accepts a callback function that is run during every render. To restrict the callback to run only when a specified value is changed, we pass in a second argument with an array of the value that we want to watch and run the callback when they change.

If we pass in an empty array as the 2nd argument, then the callback only runs when during the first render.

For instance, we can use it as follows:

import React, { useEffect } from "react";

export default function App() {
  const [name, setName] = React.useState("");
  const [data, setData] = React.useState({});

  const getData = async () => {
    const res = await fetch(`https://api.agify.io/?name=${name}`);
    const d = await res.json();
    setData(d);
  };

  useEffect(() => {
    getData();
  }, [name]);

  return (
    <>
      <input value={name} onChange={e => setName(e.target.value)} />
      <p>
        {data.name} {data.age}
      </p>
    </>
  );
}

In the code above, we have an input that changes the value of the name state as we type something in it.

Then with the useEffect hook, we watch for changes in name so that getData is called when the name value changes.

In the getData function, we call setData to set the data and display the data that’s obtained from the API call.

We should just pass in an array as the 2nd argument always so that the callback won’t run during every render accidentally.

If we need to do clean up, we should return a function inside the useEffect callback and run any cleanup code inside the callback if needed.

We can use add clean up code as follows:

import React, { useEffect } from "react";

export default function App() {
  const [mousePosition, setMousePosition] = React.useState({});
  const { x, y } = mousePosition;

  const handleMouseMove = event => {
    const { pageX, pageY } = event;
    setMousePosition({
      x: pageX,
      y: pageY
    });
  };

  useEffect(() => {
    window.addEventListener("mousemove", handleMouseMove);

    return () => window.removeEventListener("mousemove", handleMouseMove);
  });

  return (
    <>
      <p>
        ({x}, {y})
      </p>
    </>
  );
}

In the code above, we added an event handler for the mousemove event called handleMousemove , which takes the mouse position and calls setMousePosition to set the mousePosition state.

We then watch the mouse position by writing:

window.addEventListener("mousemove", handleMouseMove);

in the useEffect callback. Below it, we have:

return () => window.removeEventListener("mousemove", handleMouseMove);

to remove the mousemove event listener when the App component is no longer being rendered.

Conclusion

The useState and useEffect hook are the 2 most useful and basic hooks in the React standard library.

They let us update state and commit side effects respectively.

Categories
React Tips

React Tips — Fragments, Lists, and Events

React is one of the most popular libraries for creating front end apps. It can also be used to create mobile apps with React Native.

In this article, we’ll look at how to render a group of elements and components without a wrapper element with fragments, render lists in React apps, and handle events.

Fragments

In React, fragments are React components that don’t render anything in the DOM. We can use fragments to group components together that are rendered together.

For instance, we can write the following code to use them in our code:

import React from "react";

export default function App() {
  return (
    <>
      <h1>foo</h1>
      <h2>bar</h2>
    </>
  );
}

In the code above, the empty tags are the opening and closing tags for fragments. We used it to wrap around the h1 and h2 elements.

When we inspect the DOM in the browser developer console, we don’t see anything in the DOM that corresponds to the fragment.

We can also write out the long form of the fragment as follows:

import React from "react";

export default function App() {
  return (
    <React.Fragment>
      <h1>foo</h1>
      <h2>bar</h2>
    </React.Fragment>
  );
}

It’s the same thing, but we can pass props to it if necessary. We can’t pass props with the shorthand version.

Fragments are good for grouping anything.

Lists and Keys

We can use the array’s map method to convert array data to React components.

For instance, we can use the map method as follows to map array entries to components we display on the screen as follows:

import React from "react";

const names = ["jane", "john", "joe"];

export default function App() {
  return (
    <>
      {names.map((n, i) => (
        <p key={i}>{n}</p>
      ))}
    </>
  );
}

In the code above, we have the names array, which we mapped into a list of p elements using the map method. In the callback, we return the p element with the key prop set to a unique value. In this case, we set key ‘s value to the array index, which is unique.

It’s also good for mapping data to elements, as we do in the following code:

import React from "react";

const names = ["jane", "john", "joe"];

const Name = ({ name }) => <p>{name}</p>;

export default function App() {
  return (
    <>
      {names.map((n, i) => (
        <Name key={i} name={n} />
      ))}
    </>
  );
}

In the code above, we created the Names component, which renders the p element that we have before.

We used map the same way but set the key prop of the Name component instead.

We need to set the key prop to a unique value for each entry so that React can keep track of the element that’s being iterated over with map .

If we skip the keys, then it’s harder to React to figure out how each element should be updated when they change.

Events and Event Handlers

React and HTML event handler is different. The case is different. For instance, in HTML, we create a click handler and attach it to an element by writing the following code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script>
      const onClick = () => {
        alert("hello");
      };
    </script>
  </head>
  <body>
    <button onclick="onClick()">
      foo
    </button>
  </body>
</html>

In the code above, we have the onClick function, which is run when the click event is triggered on the button since we have:

onclick="onClick()"

on our button.

With React, we have something similar. However, the case is different and React events aren’t the same as regular HTML events. They only work on React’s Virtual DOM. The Virtual DOM is React’s representation of the real DOM on our page.

In React apps, we write something like the following to attach a click handler to a button:

import React from "react";

export default function App() {
  const onClick = () => alert("hello");

  return (
    <>
      <button onClick={onClick}>foo</button>
    </>
  );
}

In the code above, we have the onClick function, which is run when the click event on the button in the React’s Virtual DOM is triggered.

Also, we passed in reference to the onClick function rather than running it inside the attribute as we saw in the HTML example. We never run the function inside props, we always pass in the value. Otherwise, React will re-render the component infinite times.

Conclusion

Fragments let us group elements and components together without having to render a wrapper element.

Lists can be created by calling map on an array.

Events handled in React apps by attaching events to React elements. The handler function reference is passed into the appropriate prop to run the function when the event is triggered.