React: Common Mistakes in 2023
@housecor
reactjsconsulting.com
Foundation
State
JSX
Props
HTTP
Performance
Testing
File Structure
Foundation
Mistake: Using create-react-app
Solution: Vite, Next, Remix
Mistake�Separate repos for related code
Solution
Consider a monorepo (not company-wide)
Turborepo
npm/yarn/pnpm workspaces
Mistake�Not using TypeScript, Zod, msw, etc.
Solution
Mistake�Not using typescript-eslint
Solution
Use heavily, early
Mistake�Overspecifying types
Solution
Only specify when it can’t be inferred
Mistake�Lying to TypeScript
Mistake�Export default on separate line
Solution
Use func declaration
Mistake�Inconsistent order
Solution
JSX
Mistake�Overlooking reuse opportunities
Solution
Repeating JSX? Create a component.
Repeating logic? Create a hook.
Mistake�Weak/missing design system
Solution
Create design system first
Mistake�Repeated map calls
Solution
Map once
Mistake�Separate, small, single use functions
Solution
Inline small functions. More here.
reactjsconsulting.com
State
Mistake�Separating related state
Solution
Unify related state
Mistake�Multiple setState calls in a row
Solution
Unify. Consider useReducer.
Mistake�Syncing state in useEffect
Solution
Derive state
Mistake�Fetching in useEffect
Solution
React query, RSC, swr, Apollo, loader…
Mistake�Using useEffect 😉
Mistake�Using the wrong type of state
Solution
Know the 8 ways to handle state
Mistake�State too high
Solution
Mistake�Sharable state in useState
Solution
Use the URL
Mistake�Clunky array updates
const toggleSelectedPlan = (plan: Plan) => {
const currentIndex = selectedPlans.findIndex(
(selectedPlan) => selectedPlan.id === plan.id
);
const newChecked = [...selectedPlans];
� if (currentIndex === -1) {
newChecked.push(plan);
} else {
newChecked.splice(currentIndex, 1);
}
� setSelectedPlans(newChecked);
};
const toggleSelectedPlan = (planId: number) => {
setSelectedPlanIds((prev) => {
if (prev.some((id) => id === planId)) {
return prev.filter((id) => id !== planId);
}
return [...prev, planId];
});
};
Mistake�Subset arrays
Solution
Consider one array
Mistake�Needless state
Solution
Doesn’t change? Use a const.
Doesn’t render? Use a ref.
Mistake�Global state overuse
Solution
Keep state as local as possible
Mistake�Separate, related State
Solution
Group via an object
Mistake�Repeated onChange handlers
Solution
Use computed property syntax
Use context with custom component
Use a form library
Mistake�Supporting impossible states
Solution
Make the impossible, impossible
Mistake�Poor error handling
Solution
Use react-error-boundary
Create granular boundaries
Handle async, event handlers too
Mistake�Naming things “data”
Solution
Props
Mistake�Not naming vars to use object shorthand
Solution
Name consistently
HTTP
Mistake�Using fetch, Axios
Solution
Use ky
Mistake�Not caching HTTP calls
Solution
Use react-query, swr, Apollo client, etc
Performance
Mistake�useMemo, useCallback, etc everywhere
Styling
Mistake�Styling from scratch
Solution
Consider Tailwind, component libs
Mistake�No design system
Solution
Create one
Testing
Mistake�Not mocking
Solution
Use Mock Service Worker
Mistake�Not automating the browser
Solution
Use Cypress or Playwright
Mistake�Separate QA team
Solution
Collaborate, or better yet, integrate
File Structure
Mistake�Organizing files by “type”
Solution
Organize folders/files by page
Store related stuff together
Mistake�Few shared components
Solution
Create reusable components
Document them
Put them in a clear spot
Mistake�Formatting by hand
Solution
Run Prettier on save
Recommend via extensions.json
Configure CI to validate
Summary
reactjsconsulting.com
reactjsconsulting.com
reactjsconsulting.com
Consulting and training
pluralsight.com
Software courses
@housecor