From 365935d7d599dd836488698a118e67058924cd07 Mon Sep 17 00:00:00 2001 From: Andrew Musgrave Date: Thu, 25 Jul 2019 15:05:42 -0400 Subject: [PATCH 1/2] Write v3->v4 migration docs --- .../guides/migrating-from-v3-to-v4.md | 384 ++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 documentation/guides/migrating-from-v3-to-v4.md diff --git a/documentation/guides/migrating-from-v3-to-v4.md b/documentation/guides/migrating-from-v3-to-v4.md new file mode 100644 index 00000000000..66cefd2c1d0 --- /dev/null +++ b/documentation/guides/migrating-from-v3-to-v4.md @@ -0,0 +1,384 @@ +# Migrating from v3 to v4 + +Polaris v4.0.0 removes most deprecated features introduced in v3.x.x releases. If you've been fixing deprecations in minor versions as they were introduced you shouldn't have much work to do. This file describes all breaking changes that require you to update your code. + +## Table of contents + +- [Testing](#polaris-testing) +- [Component API Changes](#polaris-component-api-changes) + - [AppProvider](#polaris-appprovider) + - [Autocomplete](#polaris-autocomplete) + - [Card](#polaris-card) + - [ChoiceList](#polaris-choicelist) + - [Icon](#polaris-icon) + - [Modal](#polaris-modal) + - [Navigation](#polaris-navigation) + - [Select](#polaris-select) + - [Tabs](#polaris-tabs) +- [Removed Exports](#polaris-removed-exports) + - [WithContext](#polaris-withcontext) + - [WithRef](#polaris-withref) + - [LinkLikeComponent](#polaris-linklikecomponent) +- [Dependencies](#polaris-dependencies) +- [TypeScript](#polaris-typescript) +- [CDN Usage](#polaris-cdn) + +## Testing + +We’ve migrated to [React’s new context API](https://reactjs.org/docs/context.html) while restructuring Polaris React’s entire context structure. We now expose all our internal contexts required for testing within a single `PolarisTestProvider` component. + +**Note:** These examples use [Enzyme](https://airbnb.io/enzyme/). Other testing libraries can also be used, as shown in [these examples](https://github.com/Shopify/polaris-react/tree/master/examples). + +In v3, you could hook into Polaris React's legacy contexts using `createPolarisContext` and `polarisContextTypes`. + +```jsx +// old +import {mount} from 'enzyme'; +import {createPolarisContext, polarisContextTypes} from '@shopify/polaris'; + +export function mountWithAppProvider(node) { + return mount(node, { + context: createPolarisContext(), + childContextTypes: polarisContextTypes, + }); +} +``` + +In v4 you should to wrap your code in the `PolarisTestProvider` which +will provide all required contexts. + +```jsx +// new +import {mount} from 'enzyme'; +import {PolarisTestProvider} from '@shopify/polaris'; +import translations from '../../locales/en.json'; + +export function mountWithPolaris(node, context = {}) { + return mount(node, { + wrappingComponent: PolarisTestProvider, + wrappingComponentProps: {i18n: translations, ...context}, + }); +} +``` + +## Component API changes + +### AppProvider + +Polaris now supports multiple languages and ships with [many translations](https://github.com/Shopify/polaris-react/blob/master/locales) to support internationalization. The `i18n` prop is now required to specify the translations you wish to use. + +```jsx +// old + + +// new +import translations from '@shopify/polaris/locales/en.json'; + + +``` + +### Autocomplete + +The `Autocomplete.ComboBox.TextField` and `Autocomplete.ComboBox.OptionList` subcomponents have been removed. Use `Autocomplete.TextField` and `OptionList` instead. + +```jsx +// old + + {}} selected={[]} /> + +// new + + {}} selected={[]} /> +``` + +### Card + +The `secondaryFooterAction` prop has been removed. Pass an array of actions into `secondaryFooterActions` instead. + +```jsx +// old +Polaris + +// new +Polaris +``` + +### ChoiceList + +The `title` prop is now required. If you want the title to be visually hidden set a `title` for screen-readers and set `titleHidden` to hide it from view. + +```jsx + +``` + +### Icon + +The `source` prop no longer accepts a string that refers to a bundled icon name or an `SvgSource` shaped object. Pass in react components, such as the icons from `@shopify/polaris-icons`, into the `source` prop instead. + +Applications using sewing-kit must update to at least version v0.82.0 if they wish to load icon files from their own codebase (which uses SVGR under-the-hood to import SVG files as react components). + +```jsx +// old +; + +// new +import {PlusMinor} from '@shopify/polaris-icons'; + +; +``` + +The `untrusted` prop has been removed. Passing a string into the `source` prop now automatically implies an untrusted icon. + +```jsx +// old +; + +// new +; +``` + +### Modal + +The `Modal.Dialog` subcomponent has been removed. This was an undocumented subcomponent for private usage only. It was never intended to be a public component. + +### Navigation + +The `iconBody` prop has been removed from the `Navigation.Item` subcomponent. Pass a string into the `icon` prop instead. + +```jsx +// old +", + }, + ]} +/>; + +// new +", + }, + ]} +/>; +``` + +The `Navigation.UserMenu` subcomponent has been removed. Pass a `TopBar.UserMenu` into `TopBar`'s `userMenu` prop instead. + +### Select + +The `groups` prop has been removed. Pass groups into the `options` prop instead, which can now accept an array of groups or options. + +```jsx +// old +; +``` + +### Tabs + +The `Tabs.Panel` subcomponent has been removed. This was a undocumented subcomponent for private usage only. It was never intended to be a public component. + +## Removed Exports + +### WithContext + +The `WithContext` component has been removed. It was used as a utility to handle multiple [legacy contexts](https://reactjs.org/docs/legacy-context.html) at once. Use [modern contexts](https://reactjs.org/docs/context.html#api) and access them using providers, hooks or `Class.contextType` instead. + +```jsx +// old +function Test({context}) { + console.log(context); + return null; +} + +const TestWithContext = withContext(Consumer)(Test); + +// new with hooks +const TestContext1 = React.createContext('Polaris'); + +function Test() { + const testContext = React.useContext(TestContext1); + return

{testContext}

; +} + +// new with contextType +const TestContext2 = React.createContext('Polaris'); + +class Test extends React.Component { + static contextType = TestContext2; + + render() { + return

{this.context}

; + } +} +``` + +### WithRef + +The `WithRef` component has been removed. It was used as a utlity to place refs on components wrapped in higher-order components. Use functional components instead. + +```jsx +// old +class Input extends React.PureComponent { + inputRef = createRef(); + + focus = () => { + inputRef.current.focus(); + }; + + render() { + return ; + } +} + +const WrappedInput = compose( + hocOne, + hocTwo, + hocX, + withRef, +)(Input); + +class App extends React.PureComponent { + input = createRef(); + + componentDidMount() { + input.current.focus(); + } + + render() { + return ( + console.log('focused')} + /> + ); + } +} + +// new with hooks +function Input(props, ref) { + const inputRef = useRef(); + useImperativeHandle(ref, () => ({ + focus: () => { + inputRef.current.focus(); + }, + })); + return ; +} +const ReffableInput = forwardRef(Input); + +function App() { + const reffableInput = useRef(); + + useEffect(() => { + reffableInput.current.focus(); + }, []); + + return ( + console.log('focused')} /> + ); +} +``` + +### LinkLikeComponent + +The `LinkLikeComponent` type that describes argument you pass into `AppProvider`'s `link` prop has been removed. Use `AppProviderProps['linkComponent']` instead. + +```jsx +// old +import {LinkLikeComponent} from '@shopify/polaris-react'; + +type Link = LinkLikeComponent; + +// new +import {AppProviderProps} from '@shopify/polaris-react'; + +type Link = AppProviderProps['linkComponent']; +``` + +## Dependencies + +The peer dependencies on `react` and `react-dom` have been increased to 16.8.6 to allow us to use hooks internally. Use `yarn` or `npm` to install a recent version of React. + +```bash +# yarn +yarn add react react-dom + +# npm +npm install react react-dom +``` + +## TypeScript + +Polaris now uses default imports for React. Because of this consuming applications that use Typescript must set the [esModuleInterop](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-from-commonjs-modules-with---esmoduleinterop) compiler option to `true` in their tsconfig.json. The TypeScript team recommend this option is enabled for all new projects. + +```js +// tsconfig.json +{ + "compilerOptions": { + "esModuleInterop": true, + } +} +``` + +## CDN Usage + +Polaris now uses [`unpkg.com`](https://unpkg.com) for hosting its static styles for CSS-only usage instead of using `sdks.shopifycdn.com`. Update any stylesheet imports to use the new URL. + +```html + + + + + +``` From 7f52029b23090069b13ae47e20f251568d863220 Mon Sep 17 00:00:00 2001 From: Ben Scott Date: Tue, 27 Aug 2019 15:49:01 -0700 Subject: [PATCH 2/2] PR feedback --- .../guides/migrating-from-v3-to-v4.md | 96 +++++-------------- 1 file changed, 22 insertions(+), 74 deletions(-) diff --git a/documentation/guides/migrating-from-v3-to-v4.md b/documentation/guides/migrating-from-v3-to-v4.md index 66cefd2c1d0..fa18d04997b 100644 --- a/documentation/guides/migrating-from-v3-to-v4.md +++ b/documentation/guides/migrating-from-v3-to-v4.md @@ -108,22 +108,33 @@ The `secondaryFooterAction` prop has been removed. Pass an array of actions into The `title` prop is now required. If you want the title to be visually hidden set a `title` for screen-readers and set `titleHidden` to hide it from view. ```jsx +// old + + + +// new ``` ### Icon -The `source` prop no longer accepts a string that refers to a bundled icon name or an `SvgSource` shaped object. Pass in react components, such as the icons from `@shopify/polaris-icons`, into the `source` prop instead. +The `source` prop no longer accepts a string that refers to a bundled icon name. Pass in a React component, such as the icons from `@shopify/polaris-icons` or icons processed through [SVGR](https://www.smooth-code.com/open-source/svgr/), into the `source` prop instead. -Applications using sewing-kit must update to at least version v0.82.0 if they wish to load icon files from their own codebase (which uses SVGR under-the-hood to import SVG files as react components). +Applications using sewing-kit must update to at least version v0.82.0 if they wish to load icon files from their own codebase (which uses SVGR under-the-hood to import SVG files as React components). ```jsx // old @@ -154,7 +165,9 @@ The `Modal.Dialog` subcomponent has been removed. This was an undocumented subco ### Navigation -The `iconBody` prop has been removed from the `Navigation.Item` subcomponent. Pass a string into the `icon` prop instead. +The `Navigation.UserMenu` subcomponent has been removed. Pass a `TopBar.UserMenu` into `TopBar`'s `userMenu` prop instead. + +The `iconBody` prop has been removed from the `Navigation.Item` subcomponent. Pass a string or React Component into the `icon` prop instead. ```jsx // old @@ -182,11 +195,9 @@ The `iconBody` prop has been removed from the `Navigation.Item` subcomponent. Pa />; ``` -The `Navigation.UserMenu` subcomponent has been removed. Pass a `TopBar.UserMenu` into `TopBar`'s `userMenu` prop instead. - ### Select -The `groups` prop has been removed. Pass groups into the `options` prop instead, which can now accept an array of groups or options. +The `groups` prop has been removed. Pass an array of groups into the `options` prop instead, which can now accept an array of groups or options. ```jsx // old @@ -261,69 +272,6 @@ class Test extends React.Component { The `WithRef` component has been removed. It was used as a utlity to place refs on components wrapped in higher-order components. Use functional components instead. -```jsx -// old -class Input extends React.PureComponent { - inputRef = createRef(); - - focus = () => { - inputRef.current.focus(); - }; - - render() { - return ; - } -} - -const WrappedInput = compose( - hocOne, - hocTwo, - hocX, - withRef, -)(Input); - -class App extends React.PureComponent { - input = createRef(); - - componentDidMount() { - input.current.focus(); - } - - render() { - return ( - console.log('focused')} - /> - ); - } -} - -// new with hooks -function Input(props, ref) { - const inputRef = useRef(); - useImperativeHandle(ref, () => ({ - focus: () => { - inputRef.current.focus(); - }, - })); - return ; -} -const ReffableInput = forwardRef(Input); - -function App() { - const reffableInput = useRef(); - - useEffect(() => { - reffableInput.current.focus(); - }, []); - - return ( - console.log('focused')} /> - ); -} -``` - ### LinkLikeComponent The `LinkLikeComponent` type that describes argument you pass into `AppProvider`'s `link` prop has been removed. Use `AppProviderProps['linkComponent']` instead.