Migrating from v0 to v1
See original GitHub issueMigrating from v0 to v1
I think experimentation is the only way to get things right. In v0, we’ve been experimenting a lot, often with approaches that were controversial by the time we came up with them. Some of them worked. Some others, not so much. I tried to keep the good things in v1, improve the things that could be improved and discard the ones that weren’t good at all.
I’ve been working on this v1 directly since November 2018, when I started writing this gist as an attempt to come up with a hooks-only API. I even implemented an early version of this in a private project to finally realize that a hooks-only API doesn’t provide much ergonomics for most developers, but it’s really amazing for composability.
This is intended to be a living document. I’m going to update it over time, and I hope it’s finished by the time v1 comes out of beta. If something is missing here, please comment down.
🚨 Important note 🚨
There are many breaking changes. And I understand that people may get a little upset about it. If v0.x
is working well for you, there’s no need to upgrade to v1
so soon. The same happened to Rebass and Material-UI, for example. I’ll keep merging bug fixes into the v0 branch and you can keep accessing the v0 docs. Take your time and make a gradual migration only when necessary (for example, if you need some new feature that’s only available in v1
).
Gradual migration
You can leverage Yarn’s ability to install multiple versions of a package:
yarn add reakit-next@npm:reakit@1.0.0-beta.0
import { Provider as ReakitProvider } from "reakit"; // v0
import { Provider as NextReakitProvider } from "reakit-next"; // v1
Alternatively, if it’s not enough, there may be a Reakit v0 version with a /next
path.
No styled-components
Dependency on styled-components has been removed, which means we don’t re-export its members anymore. You’re free to use any version of SC or another CSS library without worrying about bundle size.
Before:
import { styled, Box } from "reakit";
After:
import { Box } from "reakit";
import styled from "styled-components";
Primitives
Since the core library doesn’t care about styles anymore, these styled components have been removed. They can be re-created with styled-components.
Before:
import { Block, Flex, Grid, Inline, InlineBlock, InlineFlex } from "reakit";
After:
import { Box } from "reakit";
import styled from "styled-components";
const Block = styled(Box)`display: block;`;
const Flex = styled(Box)`display: flex;`;
const Grid = styled(Box)`display: grid;`;
const Inline = styled(Box)`display: inline;`;
const InlineBlock = styled(Box)`display: inline-block;`;
const InlineFlex = styled(Box)`display: inline-flex;`;
CSS Props
Since the core library doesn’t care about styles anymore, these props have been removed. You can use inline style directly.
Before:
<Box marginRight={100} color="red" />
After:
<Box style={{ marginRight: 100, color: "red" }} />
as
/use
props
In v0.16, we introduced the use
prop as a replacement to the as
prop. The main motivation behind this change was that the as
prop conflicted with the styled-components’ one. And, since Reakit’s one behaved differently (by accepting an array of components, for example), that made sense to rename the prop.
Now that we’re not limited to styled-components anymore and this works exactly like in other libraries (accepting only one component), we’re back to the as
prop for consistency.
Before:
<Hidden use="div" />
<Hidden use={Button} />
<Hidden use={[Button, "div"]} />
After:
<Hidden as="div" />
<Hidden as={Button} />
// using render props: https://reakit.io/docs/basic-concepts/#render-props
<Hidden>{props => <Button as="div" {...props} />}</Hidden>
Theming
Reakit doesn’t depend on styled-components anymore. You can use Reakit v0 theme by wrapping components with your own version of styled-components.
Before:
import { Provider, Button, css } from "reakit";
const theme = {
Button: css`
color: red;
`;
};
<Provider theme={theme}>
<Button />
</Provider>
After:
import { Button as ReakitButton } from "reakit";
import { ThemeProvider, styled, css } from "styled-components";
const theme = {
Button: css`
color: red;
`;
};
const Button = styled(ReakitButton)(props => props.theme.Button);
<ThemeProvider theme={theme}>
<Button />
</ThemeProvider>
Hidden
Hidden.Container
has been replaced by the useHiddenState
hook. Hidden.Show
, Hidden.Hide
and Hidden.Toggle
have been removed. HiddenDisclosure
can be used instead.
Before:
import { Hidden } from "reakit";
function MyHidden() {
return (
<Hidden.Container>
{hidden => (
<>
<Hidden.Show {...hidden}>Show</Hidden.Show>
<Hidden.Hide {...hidden}>Hide</Hidden.Hide>
<Hidden.Toggle {...hidden}>Toggle</Hidden.Toggle>
<Hidden {...hidden}>Hidden</Hidden>
</>
)}
</Hidden.Container>
);
}
After:
import { useHiddenState, Hidden, HiddenDisclosure } from "reakit";
function MyHidden() {
const hidden = useHiddenState();
return (
<>
<button onClick={hidden.show}>Show</button>
<button onClick={hidden.hide}>Hide</button>
<HiddenDisclosure {...hidden}>Toggle</HiddenDisclosure>
<Hidden {...hidden}>Hidden</Hidden>
</>
);
}
Overlay
Overlay
has been replaced by Dialog
.
Before:
import { Overlay, Backdrop } from "reakit";
function MyOverlay() {
return (
<Overlay.Container>
{overlay => (
<>
<Overlay.Show {...overlay}>Click me</Overlay.Show>
<Backdrop use={Overlay.Hide} {...overlay} />
<Overlay {...overlay}>Overlay</Overlay>
</>
)}
</Overlay.Container>
);
}
After:
import { useDialogState, Dialog, DialogDisclosure, DialogBackdrop } from "reakit";
function MyOverlay() {
const dialog = useDialogState();
return (
<>
<DialogDisclosure {...dialog}>Click me</DialogDisclosure>
<DialogBackdrop {...dialog} />
<Dialog {...dialog} aria-label="My overlay">Dialog</Dialog>
</>
);
}
Popover
TODO
Sidebar
Before:
import { Button, Backdrop, Sidebar } from "reakit";
function MySidebar() {
return (
<Sidebar.Container>
{sidebar => (
<>
<Button use={Sidebar.Show} {...sidebar}>
Open sidebar
</Button>
<Backdrop use={Sidebar.Hide} {...sidebar} />
<Sidebar {...sidebar}>Sidebar</Sidebar>
</>
)}
</Sidebar.Container>
);
}
After:
import { useDialogState, Dialog, DialogDisclosure, DialogBackdrop } from "reakit";
import styled from "styled-components";
const Sidebar = styled(Dialog)`
position: fixed;
top: 0;
left: 0;
height: 100vh;
overflow: auto;
`;
function MySidebar() {
const dialog = useDialogState();
return (
<>
<DialogDisclosure {...dialog}>Open sidebar</DialogDisclosure>
<DialogBackdrop {...dialog} />
<Sidebar {...dialog}>Sidebar</Sidebar>
</>
);
}
Step
If people find it useful, it’s possible to have this component in Reakit again in v1. In the meanwhile, it can be re-created with Hidden
and useRoverState
.
Before:
import { Step, Button } from "reakit";
function MyStep() {
return (
<Step.Container initialState={{ current: 0 }}>
{step => (
<>
<Button use={Step.Previous} {...step}>Previous</Button>
<Button use={Step.Next} {...step}>Next</Button>
<Step step="Step 1" {...step}>Step 1</Step>
<Step step="Step 2" {...step}>Step 2</Step>
<Step step="Step 3" {...step}>Step 3</Step>
</>
)}
</Step.Container>
);
}
After:
import { useRoverState, Hidden } from "reakit";
function Step(props) {
const ref = React.useRef();
React.useEffect(() => {
props.register(props.step, ref);
return () => props.unregister(props.step);
}, [props.register, props.unregister, props.step]);
return (
<Hidden
ref={ref}
visible={props.step === props.currentId}
{...props}
/>
);
}
function MyStep() {
const rover = useRoverState({ currentId: "step1" });
return (
<>
<button onClick={rover.previous}>Previous</button>
<button onClick={rover.next}>Next</button>
<Step step="step1" {...rover}>Step 1</Step>
<Step step="step2" {...rover}>Step 2</Step>
<Step step="step3" {...rover}>Step 3</Step>
</>
);
}
Tabs
TODO
Toolbar
TODO
Tooltip
TODO
Backdrop
TODO
Button
TODO
Divider
It has been replaced by Separator
to match the WAI-ARIA role.
Before:
import { Divider } from "reakit";
<Divider vertical />
After:
import { Separator } from "reakit";
<Separator orientation="vertical" />
Issue Analytics
- State:
- Created 4 years ago
- Reactions:9
- Comments:27 (12 by maintainers)
@paulbalogh Reading your comment makes me sad as I’ve worked hard to make this release the best for everyone.
I did, but I don’t see your feedback on #261 or #288 or #345 or here. I can’t find you on any of our communities so I could’ve asked privately as I did with some people. I can’t find your email listed in our mailing list so I could tell you about the
v1.0.0-alpha
release more than a month ago. I’ve been tweeting about this release sincev0.16.0
got released. Where were you? If you care that much, why didn’t you get involved?Regardless, if a version is working well for you, why do you need to upgrade it? Why not just stick with
0.16
? I’ll keep merging bug fixes into the v0 branch. If you need features that are only available inv1
, you can use the technique described in the Gradual migration section and import only that component.That said, most of the things that changed can be re-created in just one file (for everything). List the components you rely on the most, and I do my best to provide a comprehensive guide for them.
Jesus Christ, I just migrated from 0.15 to 0.16 (with lots of breaking changes, such as the
use=""
instead ofas=""
) and now I see thatas
is back and most of the components written with reakit need to be basically re-written. Absolutely crazy!!! Why would you removeFlex
andGrid
as they were immensely useful alongside with casually dropping abackgroundColor=""
when you needed it, instead of creating a style for that? You say you are more focused. Fine, but I am not sure you have asked your users enough what they liked about Reakit and what they used it for. Very disappointed fan here!