The organization has several UI apps and libraries and of them have different React versions, causing issues whenever we want to consume them. To remove these problems, and to keep every app updated, we need to move to React 17 in every UI app and lib, specially in the UI repository that contains most of our shared UI components.
Updating the UI repository to the latest version of React implies updating
react-semantic-ui
to its latest version, ending up in
a major change that removed the Responsive
component, a widely used component dedicated to conditionally rendering different components based on
their display. Removing this component will cause a breaking change in our current
UI library and will imply everyone to get on
board of this breaking change, but a different strategy can be chosen by keeping the
Responsive
component by copying it from the library until everyone gets on board
with an alternative.
We need to provide, alongside this update, an alternative library to the
Responsive
component, providing a similar or a better API for rendering
components according to device sizes.
react-semantic-ui
in our
UI library, removing
the Responsive
component and forcing everyone that wants to use our
UI library to change their code.
Responsive
component in our
UI library, without forcing a breaking
change and provide an alternative to migrate the components easily.
Responsive
in a breaking change can ensure a non-prolonged onboarding
of the alternative.
react-semantic-ui
,
[@artsy/fresnel](https://github.com/artsy/fresnel)
library.
[react-responsive](https://github.com/contra/react-responsive)
.
@artsy/fresnel
works by using a ContextProvider component that wraps the
whole application, coupling the media query solution to this library.
The option to keep the an exact copy of the Responsive
component (from the old
react-semantic-ui
lib version) was chosen in order to have a frictionless upgrade
of the library.
The procedure in which we'll be handling the upgrade is the following:
Responsive
component as a deprecated component and an alternative (describe
below) will be provided to replace it.
Responsive
component.
We’ll be providing, alongside the Responsive
component a set of components and
hooks to replace it, using the react-responsive
, library. This library was chosen
in favor of the recommended @artsy/fresnel
mainly because of its versatility. The
need of having to set a provider at the application's root level, (coupling the users of this
dependency to @artsy/fresnel
) to have better SSR support that we don't currently
need, made us decide not to go with it.
The components built with the react-responsive
and exposed to the consumers of
our UI library will be the following:
min width: 992
)min width: 768 and max width: 991
)max width: 991
, that is taking into
consideration tablets and mobile devices)
max width: 767
)These components describe a conditional rendering based on the media the page in being rendered.
Where we had:
return (
<Responsive as={Menu} secondary stackable minWidth={Responsive.onlyTablet.minWidth}>
<a className="dcl navbar-logo" href="https://decentraland.org">
<Logo />
</a>
{this.renderLeftMenu()}
</Responsive>
)
return (
<Responsive {...Responsive.onlyMobile} className="dcl navbar-mobile-menu">
<a className="dcl navbar-logo" href="https://decentraland.org">
<Logo />
</a>
<Header
size="small"
className={`dcl active-page ${this.state.toggle ? "caret-up" : "caret-down"}`}
onClick={this.handleToggle}
>
{activePage}
</Header>
</Responsive>
)
We now have:
return (
<NotMobile>
<Menu secondary stackable>
<a className="dcl navbar-logo" href="https://decentraland.org">
<Logo />
</a>
{this.renderLeftMenu()}
</Menu>
</NotMobile>
)
return (
<Mobile>
<div className="dcl navbar-mobile-menu">
<a className="dcl navbar-logo" href="https://decentraland.org">
<Logo />
</a>
<Header
size="small"
className={`dcl active-page ${this.state.toggle ? "caret-up" : "caret-down"}`}
onClick={this.handleToggle}
>
{activePage}
</Header>
</div>
</Mobile>
)
And, alongside these components, as explained before, we're exposing the following set of hooks:
Which return true if the device is the one defined as the name of the hook.
These types of hooks will provide us with newer functionality, being able to customize small portions of our code instead of forking our components into two.
As an example, we can apply certain styles by simply:
const isMobile = useMobileMediaQuery()
const classes = isMobile ? "dcl mobile" : "dcl"
return <div className={classes}>...</div>