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.

Categories
React Tips

React Tips — Setting State and Internationalization

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 how to set multiple states sequentially and the internationalization of React apps.

setState Updater Function

In React class-based components, the setState method either takes an object with the state to update or a function.

setState also takes a function, which preserves the order of how the state should be applied as well as making sure that all previous states are flushed through.

For instance, we can call setState with a callback function instead of an object as follows:

import React, { Suspense } from "react";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment() {
    this.setState((state, props) => {
      return {
        count: state.count + 1
      };
    });

    this.setState((state, props) => {
      return {
        count: state.count + 2
      };
    });
  }

  render() {
    return (
      <>
        <button onClick={this.increment.bind(this)}>Increment</button>
        <p>{this.state.count}</p>
      </>
    );
  }
}

In the code above, we have the increment method, which first increases the count by 1, then it increases the count again by 2.

Since we passed in a callback function to setState , count should increase by 3 every time that we click the Increment as the state changes are applied sequentially.

Use Prop Types to Check to Validate Prop Data

By default, React lets us pass anything from parent components to child components via props. This isn’t ideal because it’s very easy to make a mistake that may cause runtime errors in production.

Therefore, we should use React’s built-in prop-type validation feature to check the data type of props. We can also use it to check if the prop value has the format that we want them to be in.

There’s built-in prop type for common JavaScript data types. In addition, we can check for a combination of one or more types and we can also pass in a custom validation to check for the prop data.

For instance, we can use it as follows:

import React from "react";
import PropTypes from "prop-types";

const Foo = ({ data }) => {
  return <p>{data}</p>;
};

Foo.propTypes = {
  data: PropTypes.string
};

export default function App() {
  return <Foo data="bar" />;
}

In the code above, we have:

Foo.PropTypes = {
  data: PropTypes.string
};

to check that the data prop is indeed a string. In the code above, we passed in a string as the value of the data prop. Therefore, we should see the p element displayed with the text ‘bar’ inside.

Otherwise, we would get an error.

We can add our own prop data validation as follows:

import React from "react";

const Foo = ({ data }) => {
  return <p>{data}</p>;
};

Foo.propTypes = {
  data(props, propName, componentName) {
    if (!/bar/.test(props[propName])) {
      return new Error("I want bar");
    }
  }
};

export default function App() {
  return <Foo data="baz" />;
}

In the code above, we have:

Foo.propTypes = {
  data(props, propName, componentName) {
    if (!/bar/.test(props[propName])) {
      return new Error("I want bar");
    }
  }
};

Therefore, if we didn’t pass in 'bar' as the value of the data prop into Foo , we’ll get the error ‘I want bar’ logged in the console. We pass in 'baz' , so we’ll get the error.

Internationalization

The react-intl library is great for internationalization of React apps. It’s made by Yahoo. It has lots of components for doing various things like formatting dates for a specific locale, pluralization and more.

We can install it by running:

npm i react-intl

For instance, we can use it as follows:

import React from "react";
import { IntlProvider, FormattedDate } from "react-intl";

export default function App() {
  return (
    <IntlProvider locale="fr">
      <FormattedDate value={new Date(2019, 0, 1)} weekday="long" />
    </IntlProvider>
  );
}

In the code above, we referenced the IntlProvider component from react-intl , and inside it, we have the FormattedDate component to format the date that’s passed into the value prop.

Then we should see ‘ mardi’ on the screen because we specified that the locale is 'fr' , which is French.

react-intl has many other components that we can use to make internalization easy, so we should use this instead of writing the code ourselves.

Conclusion

Setting state in a component is easier if we pass in a callback function instead of an object. This is because the setting of the states will be done sequentially instead of at an indeterminate time. This makes running setState multiple times easy if we need to set them sequentially.

To make passing props less error-prone, we should use prop-types to check for the correct prop type and format when props are being passed in. React will log errors to the console the type or format doesn’t match what we specified.

Finally, the internationalization of Reach apps is easy if we use the react-intl library. It has components for doing things like formatting dates and pluralization for different locales.

Categories
React Tips

React Tips — Render Props and Forward Refs

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 how to use render props to create a component that renders things flexibly and passing refs to a child with forwarding refs.

Render Props

Render prop is a pattern where we pass in the render function as a prop. To use the pattern, we create a component that calls the render function from props. Then from another component, we pass in the render prop with the function as the value to the component which calls render .

For instance, we can write the following code:

import React from "react";

const RenderComponent = ({ render }) => {
  const [foo] = React.useState("foo");
  const [bar] = React.useState("bar");

  return render({
    foo,
    bar
  });
};

export default function App() {
  return (
    <>
      <RenderComponent
        render={({ foo, bar }) => (
          <p>
            {foo} {bar}
          </p>
        )}
      />
      <RenderComponent
        render={({ foo, bar }) => (
          <p style={{ color: "green" }}>
            {foo} {bar}
          </p>
        )}
      />
    </>
  );
}

In the code above, we have the RenderComponent , which calls the render function passed in from props. It just calls the render function that’s passed in from props with the states inside RenderComponent .

Then in App , we referenced RenderComponent twice, with the render prop set the different functions for each.

Therefore, we should see ‘foo bar’ displayed twice, with the 2nd one being green.

This is useful for formatting data differently from the same state without repeating code.

Forward Refs

Forwarding refs means that we are getting the refs from a child component from a parent component.

For instance, if we want to get the ref of a button that resides in a custom button component, we can write the following code:

import React, { useEffect } from "react";

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref}>{props.children}</button>
));

export default function App() {
  const buttonRef = React.createRef();

  useEffect(() => {
    buttonRef.current.focus();
  }, []);

  return (
    <>
      <FancyButton ref={buttonRef}>Click me!</FancyButton>;
    </>
  );
}

In the code above, we have the FancyButton component, which has the button element, which we want to access. To let us access it from App or another component, we call React.forwardRef , which takes a callback with 2 parameters, props and ref .

The props have the props, and the ref is the ref that we can access from the outside. We set the ref prop to the ref parameter so to set the ref to the button.

Then in App , we create the buttonRef and pass it into ref . Then in the useEffect callback, we call buttonRef.current.focus(); to focus the button when App load since we have an empty array as the 2nd argument.

Forwarding refs are also used with 3rd party components. For instance, if we have to use the react-hook-form package and we’re using our own custom input control components, then we have to call forwardRef as follows:

import React from "react";
import { useForm } from "react-hook-form";

const Select = React.forwardRef(({ label }, ref) => (
  <>
    <label>{label}</label>
    <select name={label} ref={ref}>
      <option value="10">10</option>
      <option value="20">20</option>
    </select>
  </>
));

export default function App() {
  const { register, handleSubmit } = useForm();

  const onSubmit = () => {};

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Select label="Age" ref={register} />
        <input type="submit" />
      </form>
    </>
  );
}

In the code above, we created a custom select control called Select , which is created by calling forwardRef with a callback that takes the ref as the 2nd parameter, we set it as the value of the ref prop in the select element.

Then we can access the ref of select from App .

Conclusion

Render props is the pattern where we pass in the render function as a prop into a child component. The child component has the states that are rendered by the function we passed into the render prop.

Then we can reference that child component multiple times with different render functions.

Forwarding refs let us access the ref of an element from a child component from within the parent. This is useful for custom components that are used for customizing an existing HTML element.

Categories
React Tips

React Tips — Elements and Caching Values

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 various less common features that are helpful for developing React apps.

Create React Elements with Strings

We can reference React elements with strings instead of JSX. HTML elements can be written with strings instead of JSX.

For instance, we can write the following code:

import React from "react";

const Component = "div";

export default function App() {
  return <Component className="App">hello</Component>;
}

In the code above, we have Component set to 'div' , which means that Component is a div element. This is good because we can change the Component ‘s element tag dynamically without hassle.

For instance, we can make a toggle to switch between div and p as follows:

import React from "react";

export default function App() {
  const [Component, setComponent] = React.useState("div");
  return (
    <>
      <button
        onClick={() =>
          setComponent(Component => (Component === "div" ? "p" : "div"))
        }
      >
        Toggle Tag
      </button>
      <Component className="App">hello</Component>
    </>
  );
}

In the code above, we have a button to toggle the tag of Component between div and p.

Therefore, when we click the button, we’ll see that the tag of Component switches between div and p as we click the button.

Retain Previous Values

We can use the useRef hook to retain the previous value of a prop or state.

For instance, we can keep the old value and the new value of a state as follows:

import React from "react";

export default function App() {
  const [name, setName] = React.useState("bob");
  const prevNameRef = React.useRef("");

  React.useEffect(() => {
    prevNameRef.current = name;
  }, [name]);

  const prevName = prevNameRef.current;

  return (
    <div>
      <button
        onClick={() => setName(name => (name === "bob" ? "jane" : "bob"))}
      >
        Toggle Name
      </button>
      <p>Current name:</p>
      <p>{name}</p>
      <p>Previous name:</p>
      <p>{prevName}</p>
    </div>
  );
}

In the code above, we have the name state and the setName function to set the value of name .

Then in the button, we call the setName function when we click it. It toggles between 'bob' and 'jane' .

In the useEffect hook, we watch the value of name , which sets the prevNameRef.current to name to keep the original value. Then we set prevNameRef.current to prevName so to keep things short in the return statement.

In the end, we’ll see the old and new values display in the returned JSX.

Use React.useRef for Flexible Non-Stale Value Checks

One way to check if some data is loaded when the component loads are to use the useRef hook to keep track of whether the piece of data is loaded.

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

import React from "react";

export default function App() {
  const [name, setName] = React.useState("");
  const loaded = React.useRef(false);

  React.useEffect(() => {
    if (!loaded.current) {
      setName("bob");
    }
    loaded.current = true;
    return () => (loaded.current = false);
  });

  return <div>{name}</div>;
}

In the code above, we check the useEffect callback that checks if loaded.current is true . If it’s not, then we call setName to set the name state’s value.

In the useEffect callback, we also have:

return () => (loaded.current = false);

to reset loaded.current to false when App unloads.

Therefore, we’ll see that the component loads with the name ‘bob’ displayed.

Memoize Values with the useMemo Hook

We can also use the useMemo hook to create a memoized values, which means that it’s cached as long as it or its dependencies don’t change.

useMemo runs during rendering. Therefore, we shouldn’t run anything that we wouldn’t do during rendering.

It’s used as a performance optimization, but it’s not a guarantee of the integrity of the value because it might change later.

For instance, we can use it as follows:

import React from "react";

export default function App() {
  const [firstName, setFirstName] = React.useState("");
  const [lastName, setLastName] = React.useState("");
  const name = React.useMemo(() => `${firstName} ${lastName}`, [
    firstName,
    lastName
  ]);

  return (
    <div>
      <input value={firstName} onChange={e => setFirstName(e.target.value)} />
      <input value={lastName} onChange={e => setLastName(e.target.value)} />
      <p>{name}</p>
    </div>
  );
}

In the code above, we used useMemo to watch firstName and lastName ‘s values and then derive a new value name from combining the 2.

Then when we enter text into the input, we’ll see that it updates the value of name . However, it’ll cache the existing value if firstName or lastName don’t change.

Conclusion

We can use the useRef and useMemo hooks to cache data. Also, we can create HTML elements with strings. This means that we can render HTML elements dynamically.