Categories
React Tips

React Tips — Component Organization and Web Components

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps. In this article, we’ll look at some tips and tricks to make building apps with React easier.

Keeping Components Small

Keeping components small making them easy to read, change, and test. They’re also easier to debug and maintain. It’s more than 30 lines of code, it’s probably too big.

We can easily split up components into smaller ones by passing props between them if they’re parent and child.

If they aren’t related, we can also use a state management solution like Redux or the context API.

They do less and so they’re more likely to be reused since they fit more use cases.

For example, the following is a small component:

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0);
  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>{count}</p>
    </div>
  );
}

It’s short and it doesn’t do much on its own.

Avoid Components That are Too Small

Components that are too small are also a problem. We don’t want lots of components that are one or 2 lines. Also, we don’t want every div, span, or paragraph to be its own component.

We should make them reusable by letting them accept props. For instance, we shouldn’t have components that are like this everywhere in our app:

const Foo = <p>foo</p>;

Using Web Components in React

We can put web components straight into React components and use them.

For instance, we can define a web component and then use it as follows:

import React from "react";

class FooParagraph extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    const shadow = this.attachShadow({ mode: "open" });
    const p = document.createElement("p");
    p.setAttribute("class", "wrapper");
    p.textContent = this.getAttribute("text");
    shadow.appendChild(p);
  }
}

customElements.define("foo-paragraph", FooParagraph);

export default function App() {
  return (
    <div className="App">
      <foo-paragraph text="abc" />
    </div>
  );
}

In the code above, we have the FooParagraph web component class. Inside the class, we have the connectedCallback , which gets the attribute value for text and then add a p tag with the text ‘s value into the shadow DOM.

Then we call customElements.define to define a new web component. And then we put it straight into the App React component.

Using React in Our Web Components

We can also create web components with React by mounting our React component inside a web component as follows:

src/index.js :

import React from "react";
import ReactDOM from "react-dom";

class XParagraph extends HTMLElement {
  connectedCallback() {
    const mountPoint = document.createElement("div");
    this.attachShadow({ mode: "open" }).appendChild(mountPoint);

    const text = this.getAttribute("text");
    ReactDOM.render(<p>{text}</p>, mountPoint);
  }
}
customElements.define("x-paragraph", XParagraph);

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app"></div>
    <x-paragraph text="foo"></x-paragraph>
    <script src="src/index.js"></script>
  </body>
</html>

The code above are parts of a project that’s created with Parcel. Therefore, we can use modules in a script.

We have a XParagraph web component that has the ReactDOM.render call to render a p React element with the text attribute’s value taken from the attribute of the web component.

Then we defined the web component with customElements.define with the name of the element as the first argument, and the HTMLElement class as the second argument.

In index.html , we added the x-paragraph web component with the text attribute set to foo , so that we display the text content inside the element by calling this.getAttribute('text') and then passing in the returned value to ReactDOM.render .

Therefore, we see the word ‘foo’ on the screen.

Conclusion

To make development, testing, and reading the code easy, we should keep components small. Around 30 lines or less is a good size.

However, they shouldn’t be too small, like 1 or 2 lines, since we would have to manage too many of them. That’s even worse if they don’t take any props. To make sure that they’re reusable, we should make sure that they take props if they share any data.

React components can be embedded into web components to create easily reusable web components with React.

Also, we can embed web components in a React component so that we can take advantage of standards-compliant custom HTML elements that we can use anywhere.

Categories
React Tips

React Tips and Tricks — Fragments and Error Handling

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps. In this article, we’ll look at some tips and tricks to make building apps with React easier.

React Fragments

We can’t have multiple root nodes in a React component. However, we can have a single root node that doesn’t render any component by using a React fragment as the root node.

We can reference a React fragment with the React.Fragement component or an empty tag.

For instance, we can write the following:

import React from "react";
`
export default function App() {
  return (
    <React.Fragment>
      <p>foo</p>
      <p>bar</p>
    </React.Fragment>
  );
}

or:

import React from "react";
`
export default function App() {
  return (
    <>
      <p>foo</p>
      <p>bar</p>
    </>
  );
}

<React.Fragment> is the same as <> .

Use Error Boundaries to Handle Errors Gracefully

Error boundaries are components that are displayed when there’re errors. They have special hooks like componentDidCatch to let us retrieve error details and does actions on error accordingly.

We wrap error boundary components around components that may throw errors for them to work.

Error boundary components are always class-based components. There’s no function component equivalent for this.

For instance, we can define an error boundary component and use it as follows:

import React from "react";
`
function Foo() {
  throw new Error("error");
  return <div>foo</div>;
}
`
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  componentDidCatch(error, info) {
    this.setState({ hasError: true });
  }
  render() {
    if (this.state.hasError) {
      return <h1>Error occurred.</h1>;
    }
    return this.props.children;
  }
}
`
export default function App() {
  return (
    <ErrorBoundary>
      <Foo />
    </ErrorBoundary>
  );
}

In the code above, we defined the ErrorBoundary component, which has the componentDidCatch hook, which takes the error parameter with the error that’s raised, and info object with the error information.

Then we call setState to hasError to true so that we render an error message. We return this.props.children when there’re no errors so that we display the components that we put inside the ErrorBoundary component.

Therefore, when we have Foo , where we threw an error, then we display the ‘Error occurred’ message since Foo throws an error before rendering anything.

Higher-Order Components

Higher-order components are components that render other components. It’s useful because it can be used to produce components that are modified by the higher-order component.

For instance, we can create a colorizeElement higher-order component to apply the color prop to a component with the value blue as the default. If the color prop is set, then it’ll override the value of the color prop that we pass inside.

We can create and use it as follows:

import React from "react";
`
const colorizeElement = Element => props => <Element color="blue" {...props} />;
`
const Foo = ({ color }) => {
  return <p style={{ color }}>foo</p>;
};
`
const ColoredFoo = colorizeElement(Foo);
`
export default function App() {
  return (
    <>
      <ColoredFoo color="red" />
      <ColoredFoo />
    </>
  );
}

In the code above, we have the ColoredFoo component that we created from the colorizeElement higher-order component. In the component, we pass in the Element , which is a React component, which returns a new function with props as a parameter and returns the Element with the color prop set as 'blue' and also pass in other props that are passed in.

Then in App , we have the ColoredFoo components, one with color prop set and the other one without. Then the first one is red and the second is blue.

React DevTools

React dev tools is an extension for Chrome and Firefox and it’s maintained by the React core team. It lets us inspect the values of props and states that are inside components.

We’ll run into bugs and issues that are hard to solve eventually, so it’s a handy tool for debugging.

Conclusion

Error boundaries and higher-order components are great for displaying errors and modifying components respectively.

Fragments are great for rendering multiple items within one single root node. It doesn’t render any HTML element itself.

React dev tools is a great extension for debugging.

Categories
React Tips

React Tips — Async and setState

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps.

In this article, we’ll look at the async nature of setState and how we should write our code to run multiple setState calls sequentially.

setState’s Asynchronous Nature

The setState method is the method to update the component’s internal state. It’s an asynchronous method that’s batched. This means that multiple setState calls are batched before a component is rerendered with the new state.

setState doesn’t immediately mutate the state but creates a pending state transaction. This means that accessing the state immediately after call setState can possibly return the old value.

The setState method takes up to 2 arguments. We usually pass in only one. The first argument can be an object or a callback that’s used to update the state.

The second argument is a function that’s always run after setState is run. For instance, we can pass in a callback in the 2nd argument as follows:

import React from "react";
`
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
`
  update() {
    this.setState(
      ({ count }) => ({
        count: count + 1
      }),
      () => {
        this.setState(({ count }) => ({
          count: count + 2
        }));
      }
    );
  }
`
  render() {
    return (
      <>
        <button onClick={this.update.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
      </>
    );
  }
}
`
export default App;

In the code above, we have:

update() {
  this.setState(
    ({ count }) => ({
      count: count + 1
    }),
    () => {
      this.setState(({ count }) => ({
        count: count + 2
      }));
    }
  );
}

which calls setState once, and then calls setState again in the callback. This will ensure that one will run after the other.

Therefore, when we click the Increment, the count state will increase by 3 every time.

setState Takes an Object or Function

As we can see from the code above, setState can take a callback that returns the new state based on the previous state. This is useful for updating states that are based on the previous state.

In the code above, the new count is based on the old count , so passing in a callback is more appropriate than passing in an object since we can guarantee that the original state is the lastest when it’s passed in as the callback parameter.

It also takes a props parameter as the second parameter which has the props. For instance, we can use it as follows:

import React from "react";
`
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
`
  update() {
    this.setState(({ count }, { incrementVal }) => ({
      count: incrementVal + count
    }));
  }
`
  render() {
    return (
      <>
        <button onClick={this.update.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
      </>
    );
  }
}
`
export default function App() {
  return <Counter incrementVal={5} />;
}

In the code above, we have the Counter component, which has the update method as we have in the previous example. But this ti,e, the setState method takes a callback which has a second parameter. It has the props object.

We can get the prop property values as we did above via the destructuring assignment syntax. Also, we can access the prop object’s property like any other JavaScript object property with the dot or bracket notation.

Therefore, since we have:

<Counter incrementVal={5} />

in App , when we click the Increment button, the count state in Counter will update by 5 since that’s what we specified.

The most common entity that we pass into setState is probably an object. We just pass in an object that has state properties that we want to change. The ones that aren’t included will stay the same.

For instance, if we write:

import React from "react";
`
class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0, foo: "foo" };
  }
`
  update() {
    this.setState({ count: this.state.count + 1 });
  }
`
  render() {
    return (
      <>
        <button onClick={this.update.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
        <p>{this.state.foo}</p>
      </>
    );
  }
}
`
export default function App() {
  return <Counter />;
}

Then this.state.foo has the value 'foo' even after this.setstate in update is run.

Therefore, when we click the Increment button, we see ‘foo’ displayed no matter how many times we click it.

Conclusion

setState calls may not be always sequential. The batching sometimes may not be controlled by React. Therefore, if we want to make sure that multiple setState calls run sequentially all the time, we should run the second setState in the callback that’s passed in as the 2nd argument of setState .

Also, setState can take an object or a function with the previous state and the props objects as the 1st and 2nd parameters respectively.

Categories
React Tips

React Tips and Tricks You May Have Missed

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps. In this article, we’ll look at some tips and tricks to make building apps with React easier.

Use React Hooks In Functional Components

Hooks make React function components smart. Without hooks, all we can use function components to display data. That’s why they were also called stateless components. With hooks, they have their own internal state and methods, which make them much more useful.

For instance, we can write components with hooks as follows:

import React from "react";

export default function App() {
  const [count, setCount] = React.useState(0);
  return (
    <div className="App">
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <p>{count}</p>
    </div>
  );
}

In the code above, we have the built-in React useState hook which lets us change the count state with the setCount function.

We call setCount with an argument to update the value as we did with the onClick handler.

It looks simple. We don’t have to reference this as we do with class components, so we don’t have call bind to set the right this as we do with class components.

It’s just much cleaner to work with. We can also write our own hooks to update data our way.

Function components don’t have access to lifecycle methods, so this is the way to make smart function components.

Use The React Context API For Passing Props

The React context API lets us pass data between unrelated components. With function components we can use the createContext method to create a context. We can use the returned component to wrap around our components which we want to share data between.

Then we can pass any data that we want between them. The communication is still one way. Data is passed from context provider to consumer.

For instance, we can write the following code to pass data between them:

import React from "react";
const CountContext = React.createContext(0);

function Count() {
  const count = React.useContext(CountContext);
  return <p>{count}</p>;
}

export default function App() {
  const [count, setCount] = React.useState(0);
  return (
    <CountContext.Provider value={count}>
      <div className="App">
        <button onClick={() => setCount(count + 1)}>Increment</button>
        <Count />
      </div>
    </CountContext.Provider>
  );
}

In the code above, we created a React with React.createContext so that we can share data with the Count component.

We use the CountContext.Provider component to wrap it around everything. Then we pass in the count variable into as the value of the value prop, which will share it with any component that calls React.useContext and is inside the CountContext.Provider component.

Then in Count , we call React.useContext with our CountContext passed in. Therefore, the count will be passed from App in Count via the value prop and rendered in Count .

Therefore, when we click the Increment, then the count value will increase.

Styled Components

One benefit of using React is it’s very easy to set CSS values in JS. Therefore, it’s very easy to make styled-components with CSS inside components, making them self contained.

We can use the style-components library to make styled-components easily. It comes with template tags that turns CSS strings we pass in into a component.

For instance, we can write the following:

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

const Div = styled.div`
  background: ${props => (props.primary ? "green" : "white")};
  color: ${props => props.color};

margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid green;
`;

export default function App() {
  return (
    <div className="App">
      <Div background="green" color="white" primary={true}>
        foo
      </Div>
    </div>
  );
}

In the code above, we have the props in the template string, which are props that we pass in when we use the component. style.div is a template tag. Template tags are functions that take in a template string and return some objects on our choice.

In this case, we return a styled component. style.div returns a div with the types that we hard code or set according to props.

Then when we reference Div in App , we’ll see a green box with white text as we specified with the color prop. Since we specified that the value of the primary prop is true , style-component will set the background color to green.

Conclusion

The hooks API makes React components cleaner and easier to understand. It lets us make function components smart. We also don’t have to worry about the value of this or lifecycle hooks any more.

The context API is useful for sharing data between 2 components, regardless of their relationship. We can use the useContext hook to do the sharing.

Finally, the styled-components library comes with template tags to let us make styled-components with ease.

Categories
React Tips

React Tips — Conditionals

React is the most used front end library for building modern, interactive front end web apps. It can also be used to build mobile apps.

In this article, we’ll look at some tips for rendering conditional expressions and statements.

Conditionals IIFEs

Adding conditional expressions in JSX has some tricky parts. If we want to render conditional statements inside JSX code, we can only use expressions. Therefore, we can’t use if blocks inside JSX easily.

One good use for immediately-invoked function expressions (IIFEs) is to put conditional statements inside an anonymous function and then call it immediately.

For instance, we can write the following code to do that:

import React from "react";

export default function App() {
  const [num, setNum] = React.useState(1);
  return (
    <div className="App">
      <button onClick={() => setNum(Math.ceil(Math.random() * 5))}>Draw</button>
      <p>
        {(() => {
          if (num === 1) {
            return "one";
          } else if (num === 2) {
            return "two";
          } else if (num === 3) {
            return "three";
          } else if (num === 4) {
            return "four";
          } else if (num === 5) {
            return "five";
          }
        })()}
      </p>
    </div>
  );
}

In the code above, we have the IIFE with the if block:

(() => {
 if (num === 1) {
   return "one";
 } else if (num === 2) {
    return "two";
 } else if (num === 3) {
    return "three";
 } else if (num === 4) {
    return "four";
 } else if (num === 5) {
    return "five";
 }
})()

It’s an expression so, it can be inside JSX code. We can also substitute the if...else with one switch in our example.

Also, we can move the function out of the JSX and call it from inside the JSX code as follows:

import React from "react";

export default function App() {
  const [num, setNum] = React.useState(1);
  const getResult = () => {
    if (num === 1) {
      return "one";
    } else if (num === 2) {
      return "two";
    } else if (num === 3) {
      return "three";
    } else if (num === 4) {
      return "four";
    } else if (num === 5) {
      return "five";
    }
  };
  return (
    <div className="App">
      <button onClick={() => setNum(Math.ceil(Math.random() * 5))}>Draw</button>
      <p>{getResult()}</p>
    </div>
  );
}

The code above is cleaner than putting a big IIFE inside the JSX code.

&& Operator

To conditionally display something inside a piece of JSX code, we can use the && operator as follows:

import React from "react";

export default function App() {
  const [show, setShow] = React.useState(false);

  return (
    <div className="App">
      <button onClick={() => setShow(show => !show)}>Toggle</button>
      <p>{show && <span>foo</span>}</p>
    </div>
  );
}

In the code above, we have the show boolean which controls whether <span>foo</span> is shown. It’s shown if show is true because of short-circuiting evaluation.

If show is true , then the 2nd operand will be evaluated since the && operator returns true if both operands returns true .

Ternary Operator

Another case if we want to display one thing if a condition is true and displays something else if the same condition is false . We can do that with the ternary operator, which returns one thing if the given condition is true and returns something else is the given condition is false .

For instance, we can make a toggle that shows ‘foo’ and ‘bar’ when then button is clicked as follows:

import React from "react";

export default function App() {
  const [show, setShow] = React.useState(false);

  return (
    <div className="App">
      <button onClick={() => setShow(show => !show)}>Toggle</button>
      <p>{show ? <span>foo</span> : <span>bar</span>}</p>
    </div>
  );
}

Separate Presentational Component

Finally, we can write return statements to conditionally return the JSX code that we want to see as the result. We can move the code that’s inside our IIFE to another component and then we can pass the result that’s generated from clicking the button and then return the things we want to display according to other prop’s value.

For instance, we can write the following code to do that:

import React from "react";

const Result = ({ num }) => {
  if (num === 1) {
    return <p>one</p>;
  } else if (num === 2) {
    return <p>two</p>;
  } else if (num === 3) {
    return <p>three</p>;
  } else if (num === 4) {
    return <p>four</p>;
  } else if (num === 5) {
    return <p>five</p>;
  }
};

export default function App() {
  const [num, setNum] = React.useState(1);
  return (
    <div className="App">
      <button onClick={() => setNum(Math.ceil(Math.random() * 5))}>Draw</button>{" "}
      <Result num={num} />
    </div>
  );
}

In the code above, we moved our if...else blocks to another component. This is cleaner since Result is a presentational component that takes the num prop and displays what’s there. The App component has the main logic.

The code above is an example of clean separation between the container and presentational components. Container components have the logic, and presentational components display what’s given.

Conclusion

Conditionals can be written in many ways in React components that use JSX. For the simplest conditionals like conditionally displaying a single element or component, we can use the && operator.

If we want to be able to toggle between 2 components and elements depending on a single condition, we can use the ternary operator.

To add if...else statements in our code, we can add a function to an existing component to return the result either as an IIFE inside the JSX code, a separate function inside the component or in a separate component that’s only used for presentation.