Back to Styled Components

Migration V4

sections/faqs/migration-v4.mdx

latest4.5 KB
Original Source

What do I need to do to migrate to v4?

Historical note: This migration guide is for upgrading from v3 to v4 (released 2018). If you're on a recent version, see the v6 migration guide instead.

This is a pretty big release with lots of changes both under the hood and at the API level.

  1. Upgrade to the latest styled-components:
sh
npm install styled-components@^4.0.0
  1. Make sure your application is using react >= 16.3; internally we are using the new React.forwardRef API and new context APIs if you wish to try and polyfill for older React version support
sh
npm install react@^16.3 react-dom@^16.3

If you are using enzyme or other dependencies like react-test-renderer, there may be more related upgrades to complete if you are coming from an old version of react.

  1. If you are using the .extend API, switch your components to use styled(StyledComponent) instead.

A codemod is available to expedite this.

🚫

tsx
import styled from 'styled-components'

const Component = styled.div`
  background: blue;
  color: red;
`

const ExtendedComponent = Component.extend`
  color: green;
`

āœ…

tsx
import styled from 'styled-components'

const Component = styled.div`
  background: blue;
  color: red;
`

const ExtendedComponent = styled(Component)`
  color: green;
`

See the "extending styles" documentation for more examples.

  1. If you were using the injectGlobal API to add global styles to your page, use the new createGlobalStyle helper component instead.

A codemod is available to expedite this.

🚫

tsx
import { injectGlobal } from 'styled-components'

injectGlobal`
  body {
    color: red;
  }
`

āœ…

tsx
import { createGlobalStyle } from "styled-components"

const GlobalStyle = createGlobalStyle`
  body {
    color: red;
  }
`

// later in your app's render method
<React.Fragment>
  <Navigation />
  <OtherImportantTopLevelComponentStuff />
  <GlobalStyle />
</React.Fragment>

See the documentation for createGlobalStyle to see all the cool stuff you can do with it that wasn't possible before with injectGlobal!

  1. If you were using the innerRef prop, change it to a normal ref.

🚫

tsx
const Component = styled.div`
  background: blue;
  color: red;
`

// later in your render method
<Component innerRef={element => { this.myElement = element }}>Something something</Component>

āœ…

tsx
const Component = styled.div`
  background: blue;
  color: red;
`

// later in your render method
<Component ref={element => { this.myElement = element }}>Something something</Component>
  1. If you're using the keyframes component in a partial without the css helper, you'll need to use the helper now. In general, always use the css helper when composing styling partials to be interpolated into a styled component.

🚫

tsx
import styled, { keyframes } from 'styled-components'

const animation = keyframes`
  0% {
    opacity: 0;
  }

  100 {
    opacity: 1;
  }
`

const animationRule = `
  ${animation} 1s infinite alternate
`

const Component = styled.div`
  animation: ${animationRule};
`

āœ…

tsx
import styled, { css, keyframes } from 'styled-components'

const animation = keyframes`
  0% {
    opacity: 0;
  }

  100 {
    opacity: 1;
  }
`

const animationRule = css`
  ${animation} 1s infinite alternate;
`

const Component = styled.div`
  animation: ${animationRule};
`
  1. If you're using attrs({}) and some of the attributes you pass to it is a Function, it's recommended to switch to the new attrs(props => ({})) syntax instead for easier and more powerful composition.

🚫

tsx
import styled from 'styled-components'

const Input = styled.input.attrs({
  type: props => props.inputType,
})`
  background: blue;
  color: red;
`

āœ…

tsx
import styled from 'styled-components'

const Input = styled.input.attrs(props => ({
  type: props.inputType,
}))`
  background: blue;
  color: red;
`
  1. If you're using TypeScript, note that as of v6, types are bundled with styled-components directly (no separate @types/styled-components needed).

That's it! Aside from migrating, we also highly recommend reading up on the "as" prop which replaced the withComponent API (removed in v6).