Today I Learned

A Hashrocket project

63 posts about #react

Change Styled Component via Parent state

Styled Components has been changing the way I think about CSS and styling. Including the css in with the component makes sense, you don’t have to hunt down styles or wonder what unravels when you start changing styles in a heavily nested scss document.

Today I learned that you can reference styled components in other components to allow parents to change the state of their children.

<Parent>
    <Thing/>
</Parent>

When a user hovers over Thing’s parent, I want to change it’s color from blue to red. I can do that by interpolating Thing into Parent.

const Thing = styled.div`
  color: blue;
`
const Parent = styled.div`
  &:hover {
    ${Thing} {
      color: red 
    }
  }
`

Run One Jest Test

When iterating on a test, I want to run just that test. This is a bit tricky with Jest, but it can be done.

First, tell the test framework to run a file, or a describe block:

 # Test file
$ yarn test path/to/test.test.js

# Describe block
$ yarn test -t 'myAssertiveDescribeBlock'

Then, add .only to your it or test block to run just that example:

it.only('is true', () => {
  // your test here
});

It’s just that easy.

only docs

Forcing A Child Remount With The Key Prop

There are a couple prop names that have reserved usage in React. One of those is key. We generally use key when we are rendering a list of things. It is a way of uniquely identifying each element in a list so that React minimizes re-rendering when parts of the list change.

We can flip this on its head and utilize key as a way of forcing a remount and re-render of a child component.

Imagine I have a component that does a number of things including rendering a component with some internal state, such as a counter.

class MyComponent extends React.Component {
  state = {
    remountKey: (new Date()).getTime(),
  }

  resetCounter = () => {
    this.setState({
      remountKey: (new Date()).getTime(),
    });
  }

  render() {
    return (
      <div>
        {/* some other stuff in my component */}

        <Counter key={this.state.remountKey} />
        <button onClick={this.resetCounter}>Reset Counter</button>
      </div>
    );
  }
}

I can force this Counter component to remount, thus resetting its state by passing it a new key value. The button can trigger this by updating the remountKey value.

Display line break content in React with just CSS

Let’s say you have an array of strings and you want to display its content inside a paragraph:

const locations = ['Location 1', 'Location 2']
<p>{locations.join('\n')}</p>

That will display all the items inline even if the line break is present :

Location 1 Location 2

Instead of adding unnecessary <br /> tags to the markup you can simply specify a css property to render line breaks:

<p style="white-space: pre-line">{locations.join('\n')}</p>

This will look like:

Location 1
Location 2

Extract a Shared Yup Validation

In a growing React app with Yup validations, schemas can become repetitive. But since the validation schema is a JavaScript object, we can extract single validations, or a group of validations.

Here’s my schema definition for an address form:

validationSchema: yup.object().shape(addressValidation)

And the address validation:

const addressValidation = {
  address: yup.string().required(),
  address2: yup.string(),
  city: yup.string().required(),
  state: yup.string().required(),
  zip: yup.string().required(),
};

Reuse this helper anytime you need to collect an address.

Spelunking Through Components With Enzyme's Dive

Most of the components we write have other components nested in them.

const Hello = ({ name }) => <h1>Hello {name}!</h1>;

const HelloContainer = (props) => (
  <div>
    <Hello {...props} />
  </div>
);

If we are to shallow render the above component using Enzyme, we’ll only see things one layer deep:

const wrapper = shallow(<HelloContainer name="World" />);
// wrapper ~= <div><Hello name="World" /></div>

If we’d like to explore a particular child of the rendered component further, we can do a little find and dive.

const wrapper = shallow(<HelloContainer name="World" />);
const helloWrapper = wrapper.find(Hello).dive();
expect(helloWrapper.text()).toEqual("Hello World!");

This allows us to make pinpoint assertions about how our components render without mounting the entire thing.

See a live example here.

h/t Vidal Ekechukwu

Use React 16 With Gatsby

Gatsby, the blazing fast static site generator for React, is tied to React 15.6. If you’ve been using React 16+ for a while, then this may come as a bit of a buzzkill.

Fortunately, there is a Gatsby plugin that lets you use React 16 with a Gatsby v1 site — gatsby-plugin-react-next.

Add it the plugin as a dependency:

$ yarn add gatsby-plugin-react-next

Then add it to the list of plugins in gatsby-config.js:

plugins: [`gatsby-plugin-react-next`];

source

Avoid The Notch With SafeAreaView On React-Native

iOS devices, especially the iPhone X, have areas of the screen that are cut off in ways that present quite a challenge to developers. One of the easiest ways to deal with rounded corners and the notch when developing for iOS is to avoid them all together.

The purpose of SafeAreaView is to render content within the safe area boundaries of a device.

import { SafeAreaView, View, Text } from 'react-native';

const App = () => {
  return (
    <SafeAreaView style={{ flex: 1, backgroundColor: "#e6e6e6" }}>
      <View>
        <Text>Safely rendered in the visible area of the device!</Text>
      </View>
    </SafeAreaView>
  );
}

The unsafe area can be styled however you like and everything inside <SafeAreaView> will be pushed into the visible area of the screen.

h/t Dillon Hafer

source

Dynamically Create HTML Elements

An HTML element can be created with a string that matches a recognized entity.

const Paragraph = 'p';
return <Paragraph>Some paragraph content</Paragraph>

This means we can dynamically create HTML elements such as headers:

const H = ({ level, ...props }) => {
  const Heading = `h${Math.min(level, 6)}`;
  return <Heading {...props} />;
};

return (
  <React.Fragment>
    <H level={1}>Header 1</H>
    <H level={2}>Header 2</H>
    <H level={5}>Header 5</H>
  </React.Fragment>
);

With some inspiration, I’ve created a live example here.

create-react-app Has A Default Test Setup File

In Configure Jest To Run A Test Setup File, I pointed to a way of configuring Jest in either the package.json or jest.config.js file with the setupTestFrameworkScriptFile value.

In a create-react-app project, this is not an option because setupTestFrameworkScriptFile is not one of the permitted config values for Jest.

There is a built-in value which happens to match what was recommended in the above post — <rootDir>src/setupTests.js.

This means that there is no configuration required. Instead, just create a setupTests.js file in the src directory of your CRA project and add any framework setup you need there. That file is already configured to run when you invoke yarn test.

source

Sync Your react-router State With Redux

If you are building a React app that uses both redux and react-router, you’ll find that you are managing app state in two places. Most of your app state is in redux. The router-specific state is component-state in the Router.

You can unify it all in redux with react-router-redux.

You’ll need to apply some middleware, combine routerReducer with the rest of your reducers, and then swap out your BrowserRouter with a ConnectedRouter. You can read about the details here.

Create Dynamically Named Custom React Components

A React element is as simple as a function that returns some valid JSX. Any function will do.

const CustomComponent = ({ children }) => {
  return (
    <React.Fragment>{children}</React.Fragment>
  );
};

This function provides us with a React component that has a fixed name — CustomComponent. With the help of the displayName property, we can create dynamically named components.

const ComponentGenerator = ({ customName, children }) => {
  const CustomComponent = ({ children }) => {
    return (
      <React.Fragment>{children}</React.Fragment>
    );
  };
  CustomComponent.displayName = customName;

  return (
    <CustomComponent>{children}</CustomComponent>
  );
};

const App = () => {
  return (
    <ComponentGenerator customName="RandomComponentName">
      Hello!
    </ComponentGenerator>
  );
}

If we inspect the generated React tree, we will not see anything called <CustomComponent>, but instead we will see our <RandomComponentName> component.

Remember, React components need to have an uppercase name.

Mock A Function That A Component Imports

You have a component that relies on an imported function, isAuthenticated().

// MyComponent.js
import React from 'react';
import { isAuthenticated } from './authentication';

const MyComponent = (props) => {
  if (isAuthenticated()) {
    return (<div>{/* ... */}</div>);
  } else {
    return (<div>Not authenticated</div>);
  }
};

You’d like to test that component without having to manage the authentication of a user. One option is to mock out that function. This can be done with some help from jest.fn() and the mock.mockReturnValue() function.

// MyComponent.test.js
// ... various testing imports

import * as authModules from './authentication';

it('renders the component', () => {
  authModules.isAuthenticated = jest.fn().mockReturnValue(true);

  const wrapper = shallow(<MyComponent />);
  expect(toJson(wrapper)).toMatchSnapshot();
});

By importing the same module and functions used by MyComponent, we are then able to replace them (specifically, isAuthenticated) with a mocked version of the function that returns whatever value we’d like. As MyComponent is being rendered, it will invoked our mocked version of isAuthenticated instead of the actual one.

You could test the other direction like so:

authModules.isAuthenticated = jest.fn().mockReturnValue(false);

Access The Latest Lifecycle Methods In An Old App

With the release of React 16.3 we have access to some new lifecycle methods and are in the first phase of what will eventually result in the deprecation and removal of componentWillMount, componentWillReceiveProps, and componentWillUpdate.

You may not be ready to move your project to React 16.3, but that doesn’t mean you can’t start migrating your lifecycle methods now. We’ll need a polyfill — react-lifecycles-compat.

import React from 'react';
import { pollyfill } from 'react-lifecycles-compat';

class MyComponent extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    // ...
  }

  render() { ... }
}
polyfill(MyComponent)

export default MyComponent;

For any of our class components for which we’d like to start using the new lifecycle methods, we just need to import the polyfill function and then transform the class component with the polyfill before exporting it.

source

React StrictMode Component

Today I tried React’s new StrictMode component. Added in React 16.3, StrictMode is, according to the release notes:

[A] tool for highlighting potential problems in an application. Like Fragment, StrictMode does not render any visible UI. It activates additional checks and warnings for its descendants.

Here’s a heavy-handed way to implement it:

// index.js

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
document.getElementById('root')

In this scenario, App and all of its children get help with:

  • Identifying components with unsafe lifecycles
  • Warning about legacy string ref API usage
  • Detecting unexpected side effects

At the time of publishing this post, this will likely mean console warnings about the use of soon-to-be-deprecated lifecycle hooks such as componentWillMount. You’ll get these errors from dependencies, too, which is why we aren’t using StrictMode until at least all our dependencies have upgraded to the latest syntax.

Debug Jest Tests In create-react-app

When you put a debugger; statement in one of your Jest tests and run yarn test, the test runner will ignore the debug statement and run to completion. This is because Jest defaults to parallelizing tests which won’t mix well with manual debugging intervention.

If we want to be able to run our Jest tests through a debugger. We will need two things. First, we need a debugging environment — Chrome’s devtools will work well for this. Second, we need our tests to run in band. The react-scripts documentation recommends adding a second, debug-specific test command to your package.json:

"scripts": {
  "test:debug": "react-scripts --inspect-brk test --runInBand --env=jsdom"
}

You can now run yarn test:debug which will start a paused debug session. Open chrome at chrome://inspect to access and open the debugging session panel. Now, debug away.

Building A React App In The Browser

There are a couple relatively new tools that give you just about everything you need to build a React app in the browser.

The first is CodeSandbox. It has a couple pre-configured environments for different technologies. The main one is React. CodeSandbox describes itself as such:

an online editor that helps you create web applications, from prototype to deployment.

The second, which just released out of beta, is Glitch which comes with projects like react-starter so that you can jump into a React project that is ready to roll. Glitch describes itself as:

the friendly community where you’ll build the app of your dreams

You can quickly build and publish React apps in either of these and share them with the world.

Test Files In create-react-app

Any .js files placed in the __tests__ directory will be treated as tests by Jest when running yarn test. If you don’t want to place all of your files in that directory and especially if you want to co-located your test files with the source files, you can name them with the .test.js or .spec.js suffixes.

Any files in your create-react-app project ending in these suffixes will be treated by Jest as test files and included in test runs.

There are more details in the docs.

Firing the blur event when a component unmounts

If an input is focused and a React component containing that input unmounts, then the blur event for that input will not fire. If you use the blur event to save the contents of the input then you are in trouble.

You can know what input/select on the page currently has the focus with document.activeElement. Combine that with the component lifecycle method componentWillUnmount() to fire blur for the currently focused element on unmount.

componentWillUnmount() {
  const input = document.activeElement()
  input.blur()
}

The documentation for activeElement says it may return <body> or null when there is no active element, so you need to protect against that.

componentWillUnmount() {
  const input = document.activeElement()
  if (input) {
    input.blur()
  }
}

Enforce Specific Values With PropTypes

Being able to constrain our user interfaces to very specific values is valuable. This makes our interfaces easier to reason about and easier to test. PropTypes in general are one of the ways that we constrain our UIs. We can go even further than simple type constraints by limiting a prop to a specific set of values, an enum if you will.

MyComponent.propTypes = {
  flavor: PropTypes.oneOf(['Vanilla', 'Chocolate', 'Strawberry']),
};

The docs say about oneOf():

You can ensure that your prop is limited to specific values by treating it as an enum.

If we use MyComponent with a value such as Pistachio, we’ll have a console warning to answer for.

source

A React Component Is Just A Bag Of Data

If you write enough React using JSX, it is easy to forget that you’re not working with markup. Everything — divs, h1s, 3rd party components, your components — all get boiled down to JavaScript objects full of data.

Any given React component is really just a bag of data. Try doing a console.log to see. Here is an example from an earlier post.

const ParentWithClick = ({ children }) => {
  return (
    <React.Fragment>
      {React.Children.map(children || null, (child, i) => {
        console.log(child);
        return <child.type {...child.props} key={i} onClick={handleClick} />;
      })}
    </React.Fragment>
  );
};

const App = () => (
  <div>
    <ParentWithClick>
      <span>Click this span</span>
    </ParentWithClick>
  </div>
);

Looking in the console, we see the following output:

Object {type: "span", key: null, ref: null, props: Object, _owner: Object…}
 type: "span"
 key: null
 ref: null
 props: Object
  children: "Click this span"
 _owner: Object
 _store: Object

It contains information about the component itself and because of the tree structure of this data, you could potentially expand the props —> children sections several times for certain components.

See a live example here.

Mapping Over One Or Many Children In React

In Dynamically Add Props To A Child Component, I talked about how a child element can be reconstituted with additional props. The approach I showed will only work in the case of a single child being nested in that component. What if you want your component to account for one, many, or even children?

React comes with a built-in function for mapping that handles these cases.

const ParentWithClick = ({ children }) => {
  return (
    <React.Fragment>
      {React.Children.map(children || null, (child, i) => {
        return <child.type {...child.props} key={i} onClick={handleClick} />;
      })}
    </React.Fragment>
  );
};

The React.Children.map function allows mapping over one or many elements and if children is null or undefined, it will return null or undefined respectively.

See a live example here.

Dynamically Add Props To A Child Component

If your component has an element nested in it, then it will receive a children prop. There are a number of things you can do beyond simply including the children as part of the rendered output of the component. One thing you can do is put additional props on the child.

const ParentWithClick = ({ children }) => {
  return (
    <children.type
      {...children.props}
      onClick={() => alert("You clicked me!")}
    />
  );
};

This ParentWithClick component will reconstitute its child component with its given props and a new onClick prop.

Here is how it can be used:

const App = () => {
  return (
    <ParentWithClick>
      <span>Hello!</span>
    </ParentWithClick>
  );
};

Click on Hello! and you’ll see the alert.

Minor caveat: multiple children and a string child will need to be handled differently.

See a live example here.

Who Is Your Favorite Child?

When we put some content inside the open and close tags of one of our components, we get access to it as the children prop.

const Parent = ({children}) => {
  return (
    <React.Fragment>
      <p>These are my favorites:</p>
      {children}
    </React.Fragment>
  );
}

const App = () => (
  <div>
    <Parent>
      Greg and Marsha
    </Parent>
  </div>
);

What happens if we also provide an explicit children prop to Parent?

const App = () => (
  <div>
    <Parent children={"Jan and Peter"}>
      Greg and Marsha
    </Parent>
  </div>
);

Which will take precedence when we destructure children in the parent component?

In the example above, we’ll still see Greg and Marsha rendered. The content placed inside the tags will take precedence over the explicit children prop.

See a live example here.

React Router Route can call a render function

In General, the React Router Route component looks like this.

<React path="/triangles" component={Triangles} />

If the current url matches /triangles then the Triangles component will render.

If you want to render something simple however, you can pass down a function with the render prop.

<React path="/helloworld" render={this.renderHelloWorld} />

With that function defined in the same parent component and returning some jsx

renderHelloWorld = () => {
  return (
    <div>Hello World!</div>
  )
}

React Anti-Pattern: defaultValue

The use of defaultValue isn’t strictly an anti-pattern, as with everything it’s context dependent. In the context of a small one form react component doing something simple I’d say defaultValue is fine. This is React in-the-small.

React in-the-large or in-the-massive is different. In large applications things change in unforseen ways. In large applications there are explicit or implicit frameworks that are upstream from your component and will affect the operation of your component. React-in-the-large will create multiple entry points to your component. Sometimes its history.push and sometimes its good ol’ Page Refresh. The state of your application will be different in both those cases.

In software that can change in many ways, defaultValue is brittle. Once rendered, an input with defaultValue is completely out of React’s hands. The value of the input cannot be changed when new information becomes available. You can change the value of the input with DOM functions, but then you’re not using React.

Outside of using a React form abstraction value is much more adaptable than defaultValue. It’s more work to setup and maybe harder to get right initially, but far more likely to suit your needs down the road.

Use withRouter To Pass Down React-Router History

A standard way to navigate with react-router besides using the Link component is to call history.push. Components that are directly rendered by a Route will have access to this and other router props. But what about other components?

The withRouter HOC gives us direct access to a history prop.

import React from 'react';
import { withRouter } from 'react-router';

const SpecialButton = withRouter(({ history, path, text }) => {
  return (
    <Button
      onClick={() => { history.push(path); }}
    >
      {text}
    </Button>
  )
});

This special button component is given the history prop via the withRouter HOC along with any props that we directly pass it. With that we are able to directly invoke a route change using history.push().

Read Only Input Elements With React

Here is an input element with a value and no onChange handler.

const MyInput = ({ value }) => {
  return (
    <input value={value} />
  );
};

React will raise a warning regarding the input element because it has a value without an onChange handler leaving React to wonder if it is intended to be a controlled or uncontrolled component.

If our intention is to have the value set but not allow the user to directly change it, we just need to let React know that.

const MyInput = ({ value }) => {
  return (
    <input readOnly value={value} />
  );
};

The readOnly prop means we don’t intend for the input to be modified by user input. The React warning will now go away.

h/t Dillon Hafer

Destructure Variables As Props To A Component

When passing down props, a redundant-feeling pattern can sometimes emerge.

const MyComponent = ({ handleChange, handleBlur }) => {
  return (
    <div>
      <OtherComponent />
      <MySubComponent handleChange={handleChange} handleBlur={handleBlur} />
    </div>
  )
};

The typing feel duplicative, as if there ought to be a better way. One option is to simply pass down all the props:

<MySubComponent {...props} />

This approach may result in passing down props that we don’t intend to pass down and clutters the flow of data in our app.

Here is another approach:

const MyComponent = ({ handleChange, handleBlur }) => {
  return (
    <div>
      <OtherComponent />
      <MySubComponent {...{handleChange, handleBlur}} />
    </div>
  )
};

Here we are taking advantage of two ES6 features. Since the naming is the same, we can use property shorthands. Then we immediately use the spread operator to splat it back out as the props to the component.

h/t Vidal Ekechukwu

Alter The Display Name Of A React Component

Components adopt their display name from the class or function that renders them. A component’s display name becomes important to know about as soon as you start digging through the React devtools interface — whether debugging or just perusing the component hierarchy, the display names of components is what you’ll see. In most circumstances, the display name is good enough as is. If you want or need to, you can change it.

const Hello = ({ name }) => {
  return (
    <h1>{name}</h1>
  );
};
Hello.displayName = "Hola";

By setting the displayName property on this component, you are able to alter what name is used by React devtools.

This can be useful when bringing in a 3rd party library or component that doesn’t use a display name that you find helpful — in particular when using Higher Order Components.

Visually Select A React Element For Inspection

Similar to the Elements tab of Chrome devtools, the React devtools extension provides a visual element selector to make it easier to inspect an element you can see in the browser.

select and inspect a react component

Open the React devtools, click the crosshair icon, hover around the browser until the element you are looking for is visually highlighted, and then click. The React component hierarchy will be expanded to reveal that element. You can now inspect it or quickly navigate to nearby elements.

Defining State In A Simple Class Component

Most class components start off with a constructor which does some initialization of the component including setting the components initial state. It might look something like the following:

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

  render() {
    if (this.state.loading) {
      return (
        <p>Loading...</p>
      );
    } else {
      // ...
    }
  }
}

If setting state is the only thing you need to do in the constructor, then you can skip the constructor all together.

class MyComponent extends React.Component {
  state = {
    loading: true
  };

  render() {
    if (this.state.loading) {
      return (
        <p>Loading...</p>
      );
    } else {
      // ...
    }
  }
}

This second example will work the same as the first, and it is a bit more concise.

Use A Ref To Autofocus An Input

When creating highly interactive interfaces with React, we are trying to make the user’s experience of our app as smooth as possible. This means that when an edit button reveals an input field, we want that field to be in focus so that the user can immediately start typing.

This is a great use for React’s ref prop. When you supply your component with a function as the ref prop, that function will be called with a reference to itself on mount and with null on unmount.

class MyAutofocusInput extends React.Component {
  focusInput = (component) => {
    if (component) {
      component.focus();
    }
  };

  render() {
    return (
      <input
        ref={this.focusInput}
        value={this.props.value}
        onChange={this.props.onChange}
      />
    );
  }
}

When this component gets rendered, the input will be focused via our focusInput function.

Note: refs only work with class components, so don’t try to use it with a functional component.

See Refs and the DOM in React’s documentation for more details.

Quickly Search For A Component With React DevTools

As the size of your React app grows, it can become challenging to track down specific components within the React DevTools extension. You opened it up with the hopes of quickly inspecting the props being received by a component, but find yourself navigating through the DOM structure instead.

The React DevTools extension provides a search bar that can be used to quickly filter out most components.

react devtools component search

The search bar is located at the top of the extension. Once you start typing the results are immediate. Then, if you hover over any of the remaining components, you’ll get some visual feedback as they are highlighted in the browser.

Dispatch Anywhere With Redux

Your React app is going to have a single top-level store which is connected to the app with the Provider component. Most of the time, when you create a connected component, you’ll create prop functions that dispatch on a redux action.

This isn’t the only place you can dispatch though.

If you export your store, then it can be imported anywhere along with its dispatch function.

// src/index.js
export const store = createStore(rootReducer);
// src/components/MyComponent.js
import { store } from '../index';
import { updateData } from '../actions';

// ...

  componentDidMount() {
    getData().then((json) => {
      store.dispatch(updateData(json));
    }
  }

See the dispatch documentation for more details.

Inactive And Active Component Styles With Radium

Radium is “toolchain for React component styling” allowing you to do comprehensive inline styling with CSS.

Often times, especially in the case of a series of nav elements, there is a need to style one element as active while styling the rest as inactive. This can be achieved with Radium by defining two groups of styles (base and active) and then relying on props to conditionally apply the active style.

import React from 'react';
import Radium from 'radium';

const styles = {
  base: {
    textDecoration: "none",
    color: "gray",
  },
  active: {
    color: "black",
    backgroundColor: "lightgray",
  },
};

let NavItem = ({ label, path, active }) => {
  return (
    <a
      href={path}
      style={[
        styles.base,
        styles[active && 'active'],
      ]}
    >{label}</a>
  );
};

NavItem = Radium(NavItem);

With Radium, our base (inactive) styles always get applied. Then, the active styles only get applied when the active prop is true. We produce a Radium-ified version of our NavItem on the last line so that Radium can handle all of the styling of the component.

Rendering Multiple Nodes With Fragments

When rendering, React expects a component to only return a single node. The DOM hierarchy of most components will easily follow this rule, but what about those components that do have multiple inline nodes?

The two solutions have been to either wrap the inline nodes in an outer div or to return them as a comma separated array of nodes. With React 16, we can avoid the deficiencies of both of these approaches by using a fragment.

Just wrap your inline nodes with a React.Fragment node. React will understand your JSX without wrapping the output DOM in a superfluous div.

render() {
  // ... more code

  return (
    <React.Fragment>
      <p>Name: {firstName} {lastName}</p>
      <p>Email: {email}</p>
      <p>Age: {age}</p>
    </React.Fragment>
  );
}

See the docs on fragments for more details.

Accessing Env Vars In create-react-app

Environment-specific configurations are an important part of most applications. You can access environment variables in your create-react-app code using process.env.

There are a couple built-in environment variables, such as NODE_ENV. Anything custom that you want to provide must be prepended with REACT_APP_. If it isn’t, that environment variable will be ignored with no warning.

The following line of code

const base_api_url = process.env.REACT_APP_BASE_API_URL;

will have access to whatever that value is in the environment when the server is started or the app is built.

Set that value inline like so:

REACT_APP_BASE_API_URL="https://api.my_app.com" yarn start

source

glamorous composition for inline styling

glamorous is a library to help style components from the component itself rather than from a css stylesheet. You create a component with style in the form of a javascript object.

require glam import 'glamorours';

const InfoSpan = glam.span({
  backgroundColor: 'none',
  width: '20%',
  margin: '0 1rem',
  padding: '0 1rem',
  display: 'inline-block',
  boxSizing: 'borderBox'
});

Later when rendering, you can use this as if it were a component.

render() {
  return (
    <div>
      <InfoSpan>
        Some Important Information
      </InfoSpan>
    </div>
  );
}

You can also compose additional glamorous components by re-using previously declared glamorous components.

const LeftSpan = glamorous(InfoSpan, {
  textAlign: 'right'
});

const RedArticle = glamorous(Article, {
  textAlign: 'left'
});

Catchall in a React Router Switch

Today we built a 404 page for a React app using React Router, via a Switch statement with no specified path. Like a default clause, it catches if none of the other routes match:

<Switch>
  <Route path="/about" component={About}/>
  <Route component={NoMatch}/>
</Switch>

On any other path besides /about, we’ll render our NoMatch component.

Custom Browser with Create React App

Sometimes Google Chrome isn’t your default browser for surfing the internet, but it is your default browser during development. With create-react-app you can specify an alternate browser to automatically open (or no browser at all), to avoid opening the wrong development browser all the time.

Just pre-pend the browser to the start script:

{
  "name": "custom-browser",
  "version": "0.1.0",
  ...
  
  "scripts": {
    "start": "BROWSER='Google Chrome' react-scripts start",
    ...
  }
}

Proxy To An API Server In Development With CRA

create-react-app is a great way to bootstrap a React project, especially if you are building a single-page app. When building an SPA, you more likely than not will have a backend API that you interact with.

You can set up your React app to interact with that backend API server in development using the proxy configuration in package.json.

// package.json
  ...
  "proxy": "http://localhost:4000",
}

This will allow you to keep your API calls nice and clean.

fetch("/api/session", ...

No need to manage some sort of host URL environment variable.

Additionally, this will remove an CORS issues because the webpackDevServer will be proxying any paths that it doesn’t recognize to the host and port that you’ve specified.

See the create-react-app docs for more details.

Legacy Refs vs Ref Callbacks

Reactjs provides a way to get references to dom elements that react is rendering through jsx. Previously, it was through what are now legacy refs:

componentWillUpdate() {
  this.refs.thing.tagName == "div";
}

render() {
  return (
    <div ref="thing"/>
  );
}

Where you can assign an element an identifier and react would keep a refs hash up to date with references to the dom for that element.

The react docs say this about the previous system.

We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases.

The new system uses callbacks

render() {
  return (
    <div ref={(div) => { console.log('tag name:', div.tagName); }} />
  );
}

This callback is called when the component mounts with a reference to the dom element as an argument. Importantly, when the component unmounts the callback is called again but this time with null as an argument.

.babelrc ignores babel settings in package.json

There are three ways to provide babel configuration listed on the usage page for babelrc. You can provide a .babelrc file, you can place a babel section in your package.json or you can declare configuration with an env option.

If you have both a .babelrc in your root dir AND a babel section in your package.json file then the settings in the package.json will be completely ignored.

This happened to me when needing to declare an extra plugin for babel that create-react-app did not provide. I ejected from create-react-app, I added a .babelrc that declared the extra plugin, and this broke the build for my app. The babel configuration for an ejected create-react-app is in the package.json file.

Inline Style Attributes Should Be Camel Cased

When adding a few quick styles to React components, you can add it directly on the tags in the JSX. To do this, use the style tag with a plain old JavaScript object of styles.

<div style={{ padding: "1em", color: "#fff" }}>

If you are using a CSS attribute that is normally hyphenated like padding-top or background-color, you’ll need to camel case it in the JSX.

<div style={{ paddingTop: "1em", backgroundColor: "#fff" }}>

This is because our styles now need to conform to JavaScript syntax rules since they are in the form of a POJO.

Read the documentation for more details.

Passing Props Down To React-Router Route

When using react-router, you’ll often use the component prop to have a certain component rendered.

<Route
  path="/my/path"
  component={MyComponent}
/>

If, however, you need to pass props down into MyComponent, then you’ll want to use the render prop with an inline function.

<Route
  path="/my/path"
  render={(routeProps) => (
    <MyComponent {...routeProps} {...props} />
  )}
/>

The two spread operator statements are essential. They will pass down the route props that Route would have passed down plus the additional set of props that you want to pass down.