Today I Learned

A Hashrocket project

104 posts about #react

Generic React Components

When props are generic like this:

inteface SelectProps<T> {
  options: T[];
  onChange: (value: T) => void;
}

function CoolSelect<T> (props: SelectProps<T>) {
    // ...
}

The generic part can be specified in JSX like this:

interface Fruit {
  name: string;
  isFruit: boolean
}

const fruits = [
  { name: 'Pumpkin', isFruit: true },
  { name: 'Avocado', isFruit: true },
  { name: 'Cucumber', isFruit: true },
  { name: 'Bell Pepper', isFruit: true },
]

funciton App() {
  return <CoolSelect<Fruit> options={fruits} />
}

See it? <CoolSelect<Fruit> options={fruits} />

Now when crafting the onChange function in this example, it’s type will be infered as this:

type OnChange = (value: Fruit) => void
funciton App() {
  return (
    <CoolSelect<Fruit>
      options={fruits}
      onChange={value => {
        if (value.isFruit && value.name === 'Bell Pepper') {
          console.log("You're blowing my mind dude!")
        }
      }}
    />
  )
}

*This syntax is available in Typescript v2.9+

Use Enzyme's `wrappingComponent` option in `mount`

Also works with shallow:

const provided = {super: 'cool', object: ['of', 'things']};

// This means that the root of the tree is going to be the provider
describe('Some Component', () => {
  it('does cool things when props change', () => {
    const target = mount(
      <CoolProvider thing={provided}
        <Component changeMe={false} />
      </CoolProvider>
  })
})

// This means that the root of the tree will be your Component
describe('Some Component', () => {
  it('does cool things when props change', () => {
    const target = mount(<Component changeMe={false} />, {
      wrappingComponent: CoolProvider,
      wrappingComponentProps: {super: 'cool', object: ['of', 'things']}
  })
})

This pattern is particularly meaningful when you want to call setProps or other methods that are only valid on the root of the component tree, because dive can’t help you there. If you want to change the props on both, you can use target.getWrappingComponent() to get at the wrapping component in the same way!

https://enzymejs.github.io/enzyme/docs/api/ReactWrapper/getWrappingComponent.html

Expo PushNotifications with pop-ups on Android

Expo has an amazing push notification service. In order to display push notifications in a pop-up style (the default on iOS) on Android, you must do two things:

  1. Create an Android push notification channel
  2. Set the priority and channelId in the push notification payload to expo.

Create channel example:

import React from "react";
import { Platform } from "react-native";
import { Notifications } from "expo";

class App extends React.Component<Props> {
  componentDidMount() {
    if (Platform.OS === "android") {
      Notifications.createChannelAndroidAsync("chat-messages", {
        name: "Messages",
        priority: "max",
        sound: true,
        vibrate: [0, 250, 500, 250]
      });
    }
  }

  render() {
    // ...
  }
}

Send PN with priority and channel example:

curl -H "Content-Type: application/json" -X POST "https://exp.host/--/api/v2/push/send" -d '{
  "to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
  "title":"New Message",
  "body": "Are you there?",
  "channelId": "chat-messages",
  "priority": "max"
}'

Prefetch images in ReactNative

When a react native app boots and there is a known set of user/group avatar urls received from an API, it may be a better user experience to load them before hand.

React Native’s Image component has a prefetch method that will save the image into the device’s image cache:

import { Image } from "react-native";

const App = () => {
  const { users, loading } = useUserFetcher();

  users.forEach(u => Image.prefetch(u.avatarURL));

  return (
    <View>
      <UserList users={users} loading={loading} />
    </View>
  );
};

RN fetch on Android requires mime type

ReactNative on Android requires a mime type when uploading files with FormData. But the only way to get the mime type of a user-chosen file is to read the file or files into memory after a user select one or more. In all of my use cases, my server didn’t care if the mimetype was in the FormData.

The easy solution is to just set the mimetype to a binary file type (e.g. application/octet-stream):

let data = new FormData();
data.append("file", {
  name: "cool.pdf",
  uri: "///files/cool.pdf",
  // MIME-type required on Android
  type: "application/octet-stream"
});

fetch("http://example.com/upload-file", data);

💅 styled-components limit prop names

💅 styled-components is one of my absolute favorite libraries! ❤️ I just have to be careful not use prop names for my components that could be interpreted as styles.

For example:

interface Props {
  position: "left-side" | "right-side";
  item: Item;
}

const ListItem= styled.View<{position: "left-side" | "right-side"}>(({position}) => ({
  backgroundColor: position === "left-side" ? "burlywood" : "skyblue";
}));

const ListItemContainer: React.FC<Props> = ({position, item}) => {
  return (
    <ListItem position={position}>
      <Text>{item.name}</Text>
    </ListItem>
  );
}

<ListItemContainer item={item} position="left-side" />

This will return an error because in StyleSheet, position must be one of absolute or relative

How to typescript react native list refs

VirtualLists (i.e. SectionList, FlatList) have always been dificult for me to describe in typescript, but the following seems to work:

interface Props {
  list: MutableRefObject<SectionList<any> | undefined>;
}

Example:

import React, { MutableRefObject } from "react";
import { SectionList, View, TouchableOpacity, Text } from "react-native";

interface Props {
  listRef: MutableRefObject<SectionList<any> | undefined>;
}

const Button = (props: Props) => {
  return (
    <TouchableOpacity
      onPress={() => {
        props.listRef.current?.scrollToLocation({
          itemIndex: 0,
          sectionIndex: 0,
          animated: true
        });
      }}
    >
      <Text>Scroll Up</Text>
    </TouchableOpacity>
  );
};

const Screen = () => {
  const listRef = useRef<SectionList<any>>();

  return (
    <View>
      <SectionList ref={listRef} />
      <Button listRef={listRef} />
    </View>
  );
};

Import GraphQL Queries Where You Need Them (CRA)

If you want to export/import your GraphQL queries in your Create-React-App, you’ll need to add a library to make it work. You can use a library called grapql.macro to use .gql or .graphql files in your app.

If you’re also using jest, you’ll need to add jest-transform-graphql and update your jest configuration to pick up these file types.

Source: https://www.apollographql.com/docs/react/integrations/webpack/#jest

React Testing Library => within nested queries

Wow, React Testing Library has a within helper to get nested searches on the dom. Check this out with this example:

const DATA = {
  movies: ["The Godfather", "Pulp Fiction"],
  tv: ["Friends", "Game of Thrones"],
};

const MyContainer = () => (
  <>
    {Object.keys(DATA).map(category => (
      <MyCategory name={category} list={DATA[category]} />
    ))}
  </>
);

const MyCategory = ({name, list}) => (
  <ul data-testid={name} role="list">
    {list.map(item => <li role="listitem">{item}</li>)}
  </ul>
);

Then let’s say if we want to assert the list of movies that this MyContainer renders and in the same order as it’s been rendered we can:

...
import { render, within } from "@testing-library/react";
import MyContainer from "../MyContainer";

describe("MyContainer", () => {
  it("tests movies", () => {
    const { getByTestId, getAllByRole } = render(<MyContainer />);

    const moviesCategory = getByTestId("movies");
    const movies = within(moviesCategory).getAllByRole("listitem");

    expect(items.length).toBe(2);
    expect(items[0]).toHaveTextContent("The Godfather");
    expect(items[1]).toHaveTextContent("Pulp Fiction");
  });
});

Real code is way more complex than this example, so this within helper function turns to be very convenient.

Apollo-React hooks can easily refetch queries

React-apollo hooks allow you to easily refetch queries after a mutation, which is useful for updating a list when you have create/update/delete mutations.

useMutation takes an argument called refetchQueries that will run queries named in the array.

import React from "react";
import { useMutation } from "@apollo/react-hooks";
import gql from "graphql-tag";
import { Button } from "react-native";
import { Item } from "./types";

const ITEM_DELETE = gql`
  mutation ItemDelete($id: ID!) {
    itemDelete(id: $id) {
      id
    }
  }
`;

interface Props {
  item: Item;
}

const DeleteItemButton = ({item}: Props) => {
  const [deleteItem] = useMutation(ITEM_DELETE, {
    variables: { id: item.id },
    refetchQueries: ["GetItemList"],
  });

  return (
    <Button title="Delete" onPress={() => deleteItem()} />
  )
}

Custom React Hook Must Use `use`

You can build your own hooks by composing existing hooks.

Here, I create a custom hook useBoolean by wrapping useState:

const useBoolean = () => useState(true);

Which I can then use in my component:

function Value() {
  const [value, setValue] = useBoolean();

  return <div onClick={() => setValue(!value)}>Click me {String(value)}</div>;
}

The react documentation very politely asks that you start the name of your hook with use. This is isn’t strictly necessary, and it will still work if you call it:

const doBoolean = () => useState(true);

But that violates the Rules of Hooks.

You can include an eslint plugin that will prevent you from breaking the rules. This plugin is installed by default in create-react-app version 3.

How to write a render prop

Hi my name is Matt. This is how to write a dependecy-inverted React component using the render prop pattern. It’s useful when you want to encapsulate and share common logic without knowing how it will be used or what children it should render. The render prop pattern is the successor to higher-order components and solves HoC’s problems with naming collisions.

If you’re on the latest version of React (>= 16.8) you should probably use a custom hook instead.

function FullName({ children, firstName, lastName }) {
    const fullName = firstName + ' ' + lastName
    return children(fullName)
}

// Usage:
function App() {
  return (
    <FullName firstName="Thor" lastName="Odinson">
        {fullName => <h1>Hello {fullName}!</h1>}
    </FullName>
  )
}

Simulate componentDidMount with a useEffect

If you want to simulate a componentDidMount class method inside your functional component, you can use the useEffect hook thusly:

const MyFunctionalComponent = () => {
   useEffect(() => {
   
     // any code here is run once 
     
   }, []); 
   
   // the empty array will be the same each 
   // time the component is called, so the useEffect
   // will not run in calls subsequent to the first
   
   return <div>Foo</div>;
}

ht: @greis

Don't async await, especially in useEffect

Often I need to setState based on an async value. With hooks this is something like:

useEffect(async () => {
    const newVal = await asyncCall();
    setVal(newVal);
});

But wait!. This throws an error. React wants the return of useEffect to be a cleanup function.

The return type of an async function is Promise. So that won’t work. Best to just put on your big developer pants and use that promise.

useEffect(() => {
    asyncCall().then(setVal);
})

There. Now our useEffect returns undefined, and React is pleased.

Here is a sandbox if you want to see for yourself.

Set the relative path of assets in a CRA app

When I build my CRA app I get a path for my assets (css, images) that begins with /static. If I deploy my app to https://something.com/myapp, then the app will try to access those asset paths at https://something.com/static/asset.css. That’s not where the asset lives. The asset lives at https://something.com/myapp/static/asset.css.

Create React App allows you to change the prefix for a the built assets with the homepage attribute in your package.json file.

You could set it to myapp:

"homepage": "/myapp"

And then the asset will have the path of /myapp/static/asset.css, but what if you want to change paths?

"homepage": "."

Setting homepage to . will make the asset always relative to index.html, allowing you to not be concerned with the path the application is deployed to.

This actually repurposes a property of the package json file that npm uses to set the homepage of an npm package, so you may find this property used in a different way in other package.json files.

See the npm docs here.

See the Create React App docs here

Override Create React App conf w/react-app-rewired

A common problem when using Create React App is changing the configured behaviour of webpack. Generally, if you want to change the webpack configuration provided by Create React App you need to eject, but eject at the very minimum adds a lot of files to your project that you may not want.

An alternative is to use react-app-rewired in combination with customize-cra.

react-app-rewired provides a file, config-overrides.js placed in your project root directory where you can override existing behaviour.

customize-cra provides a set of handy utility functions to help you override specific configurations.

For example, when using the ant design library, you can import both the component and the css for that component with one import line if you use babel-loader.

Here is an example of a config-overrides.js file that would provide that behaviour.

const { override, fixBabelImports } = require('customize-cra');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  })
);

Run side effect when a prop changes w/Hooks

There is a React Hook for side effects useEffect. You can pass useEffect a function and that function will run after each render.

useEffect(() => console.log('rendered!'));

In many cases it’s inefficient and unnecessary to call the effect function after every render. useEffect has a second argument of an array of values. If passing in this second argument, the effect function will only run when the values change.

useEffect(() => console.log('value changed!'), [props.isOpen]);

Now, you will see “value changed!” both on the first render and everytime isOpen changes.

Reminder: React Hooks are for functional components not class components. Check out the hooks api here

Get a ref to a dom element with react hooks

React Hooks are now available in React 16.8. There are 10 different hooks, you can read about them here. When I needed a ref to a dom element yesterday I reached for useRef.

const containerRef = useRef(null);

This isn’t a ref to anything unless you pass the ref to a tag.

return (<div ref={containerRef}></div>);

Now the ref will be assigned a dom element that you can use. In this example I’m using the useEffect hook to execute a side effect after the render takes place. Use the current attribute to access the current dom node.

useEffect(() => {
    containerRef.current.style = 'background-color: green;'
})

Define Your Refs with React ElementRef Flow Type

If you’re using flow in your React Native project, chances are that you are probably using refs. In this case, you’ll need to define your ref types.

Let’s say we have ref on a FlatList component from React Native:

import React from 'react'
import { FlatList } from 'react-native'
import data from './data.json'

class MyList extends React.Component {
  renderItem = () => {
    // rendering stuff
  }
  render() {
    return(
      <FlatList
        ref={l => (this.l = l)}
        data={data}
        renderItem={this.renderItem}
      />)
  }
}

Instead of being lazy and just using any, we’ll use the React.ElementRef flow type. It takes an additional typeof argument, which is the component type of your ref.

// @flow
import * as React from 'react'
import { FlatList } from 'react-native'
import data from './data.json'

class MyList extends React.Component<{}, {}> {
  l: ?React.ElementRef<typeof FlatList>
  renderItem = () => {
    // rendering stuff
  }
  render() {
    return(
      <FlatList
        ref={l => (this.l = l)}
        data={data}
        renderItem={this.renderItem}
      />)
  }
}

Node Version - 10.14.1 Flow-Bin Version - 0.107.0

Flow docs - ref functions

Edited: 9/11/2019 - Fix fat arrow, Add typing to MyList, Update description to React Native, Resolve syntax error for ref typing

Navigate With State Via @reach/router

With @reach/router, you can programmatically change your route using the navigate function. This utilizes the Context API, so its available anywhere nested under your router. To provide some data to the destination location, include a state option in the navigate call.

const onSubmit = ({ data }) => {
  /* submit logic ... */

  navigate(nextPath, { state: { data }});
}

The component that renders in response to this navigation will have access to this state.

const NextComponent = ({ location }) => {
  const { data } = location.state;

  return (
    /* ... */
  )
}

Prevent reach/router Redirect Error Screen In Dev

When using @reach/router’s <Redirect> with tools like create-react-app and Gatsby, you’ll get those tools’ development-mode error screen overlays whenever a redirect happens. This has to do with how @reach/router utilizes componentDidCatch to change the path without a render. That error screen overlay can get annoying though. Prevent it with the noThrow prop.

return (
  <Redirect to={anotherPath} noThrow />
);

React Fragments

Ordinarily React requires that each component returns a single child component. Sibling components cannot be returned in the render function:

// Valid
const MyComponent = () => (
  <div>
    <span>Chicken</span>
    <span>and</span>
    <span>Farm</span>
  </div>
);

// Invalid
const MyComponent = () => (
  <span>Chicken</span>
  <span>and</span>
  <span>Farm</span>
);

Sometimes, however, you have no need for the wrapper component and want to just render the siblings. React allows you to do this with the Fragment component, which satisfies the single child requirement without actually rendering a div in the DOM:

import {Fragment} from "react";

// Valid
const MyComponent = () => (
  <Fragment>
    <span>Chicken</span>
    <span>and</span>
    <span>Farm</span>
  </Fragment>
);

// Renders =>
<span>Chicken</span>
<span>and</span>
<span>Farm</span>

Read more about Fragments here: https://reactjs.org/docs/fragments.html

Check The Type Of A Child Component

There is a simple way to check the type of a child component.

import React from 'react';

const Hello = () => <h1>Hello</h1>;

const Greeting = ({ children }) => {
  let hello;
  React.Children.forEach(children, child => {
    if(child.type === Hello) {
      hello = child;
    }
  });

  return hello;
};

This is a comparison of the child’s type to the component constant we are looking for.

This comparison is not the most robust. For instance, Gatsby does something internally that throws off this comparison. Here is a more robust comparison.

if(child.type === Hello || child.type === <Hello />.type)

source

Wrap The Root Of A Gatsby App In A Component

Each component that is defined in the pages directory of a Gatsby app will be generated into a separate static page. Each of these pages is meant to stand on its own. Nevertheless, there is still a behind-the-scenes root component above all of these pages. There are cases where’d you like to wrap this root component with some other component, such as a Redux Provider.

This can be done using the wrapRootElement hook from the Browser API in the gatsby-browser.js file.

// gatsby-browser.js
import React from 'react';
import { Provider } from 'react-redux';

import store from './src/store';

export const wrapRootElement = ({ element }) => {
  return (
    <Provider store={store}>{element}</Provider>
  );
}

Each page and each component in your Gatsby app will now be downstream from a Redux provider meaning that they can connect to the Redux store as needed. You can use this technique for any top-level component that need to be wrapped around the entire app.

source

Gatsby 404 Static Sitemap

Iterating through a process of building many static Gatsby.js pages at once, I discovered a hacky way to see what pages have been built. Visit a page that doesn’t exist, and Gatsy’s development 404 page will provide a sitemap with links to all the static pages.

demo

It’s a little nicer than digging through the filesystem.

@reach/router Renders To A Div

Check out the following snippet that uses @reach/router.

import { Router } from '@reach/router';

const Home = () => <h1>Home</h1>;

const App = () => {
  return (
    <div className="main">
      <Router>
        <Home path="/home" />
      </Router>
    </div>
  );
}

When you visit ‘/home’, this will render in the DOM as:

<div class="main">
  <div tabindex="-1" role="group" style="outline: none;">
    <h1>Home<h1>
  </div>
</div>

Notice the extra div — that is what <Router> renders to as part of @reach/router’s accessibility features. This may throw off the structure or styling of your app. This can be fixed. Any props that you give to <Router> will be passed down to that div. For instance, you could remove the most outer div and put className="main" on the <Router>.

source

Accessing Location Within @reach/router

The API of @reach/router departs a bit from react-router in a couple ways. The location prop which you may be used to having access to automatically is instead available through the Location component.

import React from 'react';
import { Location } from '@reach/router';

const MyComponent = () => {
  return (
    <Location>
      {({ location }) => {
        return <p>Current Location: {location.pathname}</p>;
      }}
    </Location>
  );
}

This is a contrived example, but you can imagine how you’d use it to access state or even create an HOC similar to withRouter.

Formik's Validation Schema As A Function

The most straightforward way to use Formik’s validationSchema is to provide it with a Yup object defining your form’s validations.

const MyComponent = withFormik({
  // ...

  validationSchema: yup.object().shape({
    email: yup.string().required(),
    feedback: yup.string().required(),
  }),
  
  // ...
})(MyForm);

There may be a point at which you need access to the props being passed to MyComponent in order to construct the proper set of validations. Formik supports this by allowing validationSchema to be a function.

const MyComponent = withFormik({
  // ...

  validationSchema: (props) => {
    let emailSchema;
    if(props.allowAnonymous) {
      emailSchema = yup.string();
    } else {
      emailSchema = yup.string().required();
    }

    return yup.object().shape({
      email: emailSchema,
      feedback: yup.string().required(),
    });
  },
  
  // ...
})(MyForm);

When validationSchema is a function, its first argument is the set of props passed to that component.

Don't rerender if nothing changed in React 16.6.0!

React 16.6.0 came out today and React now provides a handy function to create a component that won’t rerender if it doesn’t get new props, React.memo.


const BlueComponent = () => {
  return <div>no props don't rerender</div>;
}

const MemoComponent = React.memo(BlueComponent);

BlueComponent is a component that will re-render every time it’s parent re-renders. It doesn’t take props though, so it won’t look any different based on new props. MemoComponent is a component created by passing BlueComponent to React.memo. It will not re-render when it’s parent re-renders.

Check out another example in the code sandbox below.

Edit znw4wjn914

Read more about React 16.6.0 here.

Catching errors in React (16 and up)

If an error is thrown while rendering React, React unmounts the entire tree.

In production, this might not be behaviour you want. The behaviour might be inconsequential to the user’s current path and why stop the user cold due to an unanticipated state?

React provides a function componentDidCatch to help manage exceptions and keep the consequence of the error localized to a specific part of your component tree.

This blog post describes the concept of an ErrorBoundary which can look like this:

class ErrorBoundary extends Component {
  componentDidCatch(error, {componentStack}) {
    console.log("error", error)
    console.log("componentStack", componentStack)
  }

  render() {
    return this.props.children;
  }  
}

Using the componentDidCatch lifecycle function this component will catch any error thrown by its children. If an error is thrown it will not render and none of it’s children will render, but all components in different sections of the component tree will render.

The second argumunent to componentDidCatch is an object containing a key called componentStack which is a nice stack provided by React.

H/T Josh Branchaud

Return value of snapshot in componentDidUpdate

React has a rarely used lifecycle method getSnapshotBeforeUpdate where you get the opportunity to look at your current DOM right before it changes.

The return value of this method is the third parameter of componentDidUpdate.

getSnapshotBeforeUpdate(prevProps, prevState) {
    return "value from snapshot";
}

componentDidUpdate(prevProps, prevState, snapshotValue) {
  console.log(snapshotValue);
}

The above code will output value from snapshot in the log.

The purpose for getSnapshotBeforeUpdate given in the React documentation is for making sure a value that can’t be set with rendering - like the scroll position - is exactly where you want it based on the state it was before the rerender.

My code example is here.

CSS !important Is Not Supported By Inline Styles

You can get pretty far with React’s inline styling of components. There are however a few limitations. One such limitation is that the !important clause is not supported.

If you try applying !important to an inline style like so:

<div style={{ color: "red !important" }}>
  My div
</div>

You’ll be disappointed when you open up the browser and inspect that div tag. The color rule will be ignored and excluded from the output html.

source

CRA Dependencies and ES5

At the time of this writing, create-react-app requires that all dependencies are precompiled to ES5. If they aren’t, the build will abort.

When this happened to me today, I followed a few of the recommended workarounds, eventually switching to a library that uses the older ECMA standard.

Running $ yarn build-js (or equivalent) when testing out any dependency would be a good way to surface this incompatibility upfront.

Here’s the Github issue on zipcodes-perogi where I documented my journey to this discovery.

Be specific in styled components with `&`

input[type="number"] has styles applied at a global level. I want to override some of those styles

a more specific selector takes precedence over a less specific one

So if I just define some css that is:

.myCoolInput {
  background-color: green;
}

It won’t override the more specific input[type="number"] selector’s background-color: pink.

So this styled component I have is wrong.

const GreenInput = styled.input`
    background-color: green;
`

render (
  <GreenInput type=["number"]/>
);

I need to use the & and move the className attribute to get more specificity for my style.

const GreenInput = styled(NumberInput)`
  input& {
      background-color: green;
  }
`

This outputs:

input.<GreenInputClassId> {
  background-color: green;
}

This selector has the same specificity as input[type="number"] but is declared later, so takes precedence.

Don't forget the `className` prop!!

So this is normal styled-component stuff:

const RedDiv = styled.div`
  color: red;
`

which outputs

<div class='<someClassId>'>
</div>

.someClassId { color: red; } 

And then you can wrap that div

const BlueDiv = styled(RedDiv)`
  color: blue;
`

which outputs:

<div class='<someClassId>'>
</div>

.someClassId { color: blue; } 

And you can also style existing components. If I have the component:

const CoolComponent = (props) => {
  render(
    <div></div>;
  )
};

const PurpleDiv = styled(CoolComponent)`
  color: purple; 
`

That outputs

<div></div>

It’s not purple!!

That’s because if you want to style non-styled-component components with styled-components then you have to use the className prop to set the class onto your element.

const CoolComponent = ({className}) => {
  render(
    <div className={className}></div>;
  )
};

Which outputs

<div class='<someClassId>'>
</div>

.someClassId { color: purple; } 

React-Router Location Hash #️⃣

Want to do cool things with the hash element of a URL, using React-Router? You can!

React-Router’s location contains a hash key:

{
  key: 'ac3df4',
  pathname: '/somewhere'
  search: '?some=search-string',
  hash: '#hereiam',
  state: {
    [userDefined]: true
  }
}

Anywhere location is available, pull off hash (defaults to an empty string) and have fun!

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