How I React in 2020
Redux I love you, but you're bringing me down.
Iβve been working with React for the past 3 years or so, and after experimenting with various patterns and tools, I think Iβve found my favorite way of doing things. Things that make me go to bed without thinking, βwhy havenβt I thrown my laptop off a cliff?β.
These are solely based on my personal experience. Iβm sure you can always find a better approach to solve every problem, but as of now, this is how I code React in 2020.
No JavaScript.
β¦use TypeScript instead.
The IntelliSense and the ability to inspect the code or catch errors without leaving my editor is quite nice. This allows me to rewrite or refactor my entire app with confidence and without a need to start the app or even go back and forth between browser and editor. Iβd only start the app once Iβm finished to find that itβs working as expected with (almost) no issues.
The tooling for libraries and frameworks and the community around them is simply amazing. Many of them are moving to TypeScript these days or have a separate @types
package that you can install.
/* Modal.jsx */
interface Props {
show: boolean;
id?: string;
}
const Modal: FC<Props> = props => {
// props.show -> boolean
// props.id -> string | undefined
// props.children -> ReactNode | undefined
}
There are some cases where I feel like itβs bringing my development speed down with pointless errors on unnecessary types. In these situations, I donβt really mind hack my way around it (Iβd use any
or something), because after all, these tools are meant to establish a good developer experience and not to keep them busy with things that donβt eventually affect the end product.
Components: long, and several.
And in one file. From the moment I opened my eyes to the world to this day, all I saw in React projects was one component per file and it never occurred to me to question the approach or think why. I just went with it. Well, no more.
Today my components are long, strong and healthy. I would only break them down into multiple components if they contain complex states, which in that case, Iβm going to put them into the same file. I find it easier to search, navigate and develop in a single rather than multiple files in a folder.
/* Page.jsx */
const M = () => {
// states...
return <div />
}
const E = () => {
// states...
return <div />
}
const Help = () => {
return (
<>
<M />
<E />
{ /* long jsx */ }
</>
)
}
Flatter folder structure.
I used to create a folder for each component and inside that create file for the component and create an index.ts
file to export that component. This kind of structure makes me only feel nice but in the long run itβs not really practical. Finding, renaming, or even moving a single file is a more convenient than a folder and generally there is less cognitive load involved.
Now days I would only group components in a folder when I notice they are really connected to each other and makes sense to do so. Otherwise, one file ftw.
βββ components/
β βββ Settings/
β β βββ index.ts
β β βββ SettingsApi.tsx
β β βββ SettingsDomain.tsx
β β βββ SettingsPassword.tsx
β βββ Button.tsx
β βββ Footer.tsx
β βββ Header.tsx
β βββ Layout.tsx
β βββ Table.tsx
β βββ Text.tsx
βββ store/
β βββ index.ts
β βββ settings.ts
β βββ store.ts
βββ hooks.ts
βββ utils.ts
No Redux.
Although Redux is not bad (ie. βI have been using it for too long itβs now hard for me to confess itβs badβ), with the introduction of React Hooks and the powerful libraries that came after, itβs not really worth it anymore. Mostly because the amount of boilerplate needed for small changes, especially when used with TypeScript, it quickly becomes hell.
I use internal state hooks for the components and only use global state when data needs to be accessed in several places.
For the global state I have tried some libraries and I liked all of them but so far donβt have a strong opinion on one because I tend to use internal state a lot more (I guess thatβs good?). Nonetheless, Iβd usually choose one based on how well they support TypeScript and SSR.
const VibeCheck = () => {
const isAuthenticated = useStoreState(); // Global state
const [loading, setLoading] = useState();
const [config] = useContext(ConfigContext);
return <div />
}
Tests.
β¦letβs just move on.
Boilerplates and SSR.
Iβm using CRA, Next.js and Gatsby on different projects simultaneously. CRA is for when I only want to focus on the front-end and create an app (e.g. dashboard) which doesnβt need to be rendered on the server-side.
For any SSR my first pick is Next.js, itβs incredibly simple and straightforward to work with. I can have my custom API, custom server, pages, routing and React app in one place, which is nice. kutt.it and tgdr.io are two important projects that I built with Next.js.
I use Gatsby to generate static websites and although I can do the same with Next.js, a generated website with Gatsby is very well optimised. The primary selling point for me is the plugin system and how they kinda act like middleware where I can add any functionality with just few lines of code.
Long story short, I hate webpack config and if I have to do it manually, I rather write jQuery.
Styles.
My only approach is CSS-in-JS. Iβve been using styled-components since day one. Rebass and theme-ui is a deadly combination that allows me to create custom, themeable components where helper options like padding
, margin
, flex
, etc. are added to each of them.
Iβm planning to use emotion in the future, mostly because the above libraries use emotion internally and I want to leverage the consistency and performance. Another reason is that I get weird type errors and conflicts, and Iβd usually have to use a strict version to make sure everything compiles. Otherwise Iβm gonna spend my day hitting my head on the desk.
const Alert = styled(Flex)`
${ /* styles... */ }
`;
const Launch = () => {
<Alert
alignItems={["center", "flex-start"]}
fontSize={[16, 18]}
px={[2, 3, 3, 4]}
m={2}
>
Group action in 5 minutes.
</Alert>
}
Debugging.
console.log()
.
Wrapping up.
Iβm not sure if itβs a sign of getting old or getting lazier, but at the end of the day I just want to get things done. Trying to abstract too much, writing the perfect config, deciding to whether use single quote or double quote and stuff like that may sound meaningful in short term but they distract me from my end goal which is building things I love.