✅ Keep state as local as possible. Start by declaring state in the component that uses it. Lift as needed.
✅ Store data that doesn't need to render in refs
✅ Minimize context usage
1/x...
✅ Avoid putting data that changes a lot in context
✅ Separate contexts based on when they change
✅ Place context providers as low as possible
✅ Memoize expensive operations via useMemo
✅ Avoid needless renders via React.memo
2/x...
✅ Put content that renders frequently in a separate component to minimize the amount that's rendered
✅ Split complex controlled forms into separate components
✅ Consider uncontrolled components for large, expensive forms
3/x...
✅ Consider wrapping functions passed to children in useCallback to avoid needless renders in children
✅ Consider useReducer over useState so you can pass dispatch down instead of callbacks (avoids needless renders)
✅ Split the bundle via React.lazy
4/x...
✅ Consider prefetching lazy loaded components that are highly likely to be used
✅ Streamline HTTP requests - fetch only necessary data
✅ Avoid named imports when importing third party libraries / components (doing so can bloat the bundle by importing the entire lib)
5/x...
✅ Cache HTTP requests via react-query/swr/Apollo/etc.
✅ Prefer native HTML inputs over fancy components that simulate native behaviors
Okay, that's a long enough for a Twitter thread. 😀
Okay, I've seen snarky comments that this list just means React is poorly designed.
I disagree.
1. I rarely worry about performance in React. Why? Because typically the most ergonomic thing is plenty fast. 2. Much of this advice applies to any framework.
• • •
Missing some Tweet in this thread? You can try to
force a refresh
7 things that keep teams from doing Continuous Delivery (deploying daily or even hourly):
1. Non-atomic PRs.
Solution: Each PR must be ready for a prod deploy before it can be merged to `develop`. To separate deployment from release, use a feature flag.
1/x (thread)
2. Ad-hoc release notes.
Solution: Declare release notes in CHANGELOG.md. Require an entry in this file in each PR. Validate this file has changed on each CI build. This assures the release notes are customer friendly, accurate, and complete.
2/x
3. Flakey tests.
Solution: Most tests should be unit and integration tests. Mock the API. Simplify E2E tests. E2E should merely assure each section loads. Anything more granular may lead to flakiness due to changing data.
3/x
When a measure becomes a target, it ceases to be a good measure."
— Goodhart’s Law
Example 1: Story points measure difficulty. But, if you set a target for story points completed per week, developers inflate their story point estimates to assure they hit the target.
Example 2: Tracking code coverage helps the team understand what code is tested. But if you target a certain code coverage percentage, developers game the system by writing useless tests.
Example 3: Burn down charts help estimate the completion date. But if you set a goal of burning down to zero every sprint, developers commit to less work in each sprint. And they avoid proposing any work that’s hard to estimate. This assures they can burn down to zero.
Let’s talk about the implications of researching decisions (Thread)
If I quickly make a decision, it feels unimportant. I go with my gut. I’m typically happy.
Occasionally, I decide to research a decision. More research leads to better outcomes, right?
Not necessarily...
If I heavily research a decision, the decision feels more important. I want to justify my research time. So, I search for every tradeoff. I optimize for perfection. But, because my expectations are now so high, I’m more likely to be disappointed! 🤦♂️
So, here’s the trap: The more I research a decision, the more important the decision seems. This leads to problems:
1. Overspending due to over-valuing minor differences and fear of missing out.