Elizabeth Holmes and React: when the interface deceives
Elizabeth Holmes got 135 months in prison for fraud, and her story is back in the conversation because of a documentary. The newsletter The Profile published a piece with a blunt title: the documentary "You Can See Everything" is misleading. I won't judge the film here. I'll talk about what interests me as a dev: Theranos is the biggest case I know of an interface that promised more than the system delivered. And anyone who writes React makes this kind of decision every week, on a much smaller scale.
What happened to Theranos?
A quick summary, for anyone just arriving.
Theranos promised to run hundreds of tests from a few drops of blood, on a compact machine. The company reached a valuation of about US$ 9 billion. In 2015, John Carreyrou reported in the Wall Street Journal that the technology didn't do what the company claimed. Part of the tests ran on commercial machines from other manufacturers.
In January 2022, a jury convicted Holmes of defrauding investors. The sentence came in November of the same year. After that came a US$ 452 million restitution order, shared with Sunny Balwani, the company's former president.
The point that matters for this post is a different one. According to Carreyrou's book Bad Blood, during a demonstration for Novartis the device failed and the team sent a fake result, remotely, to appear as if it had come from the machine. On screen, everything worked.
The people in the room saw a result. Nobody saw where it came from.
Why does this matter to people who write React?
Relax, I know the difference between fraud and a skeleton on a screen. Nobody goes to prison over a useState. Holmes was convicted of lying to investors, with real money and real patients involved. Comparing that to a stale dashboard would be ridiculous.
But the technical mechanism is similar, and that's why it's worth a look. The presentation layer doesn't know whether the data is true. It renders what it receives. A React component draws a fake number with the same beautiful typography as a real one.
And the front end is where people form their beliefs about the system. Your customer doesn't read the server log. Your manager doesn't open the Network tab. If the screen says "saved", the person believes it was saved.
A beautiful demo only proves that the demo works.
This gives the front end an annoying responsibility: the screen has to say what it actually knows, even when it knows very little.
Where a React interface lies without you noticing
It's almost never bad faith. It's usually haste, deadlines and a mock that stayed behind.
The classic case is sample data that survives all the way to production. Look at this snippet with TanStack Query:
const { data } = useQuery({
queryKey: ['sales'],
queryFn: fetchSales,
initialData: salesMock,
})
return <Total value={data.total} />
It looks harmless. But initialData goes into the cache as real data. While the fetch hasn't finished, or if it fails, the user sees R$ 48,320.00 from a file someone wrote one afternoon in March. Nothing on the screen warns them.
If you really want to show something provisional, use placeholderData and make that visible:
const { data, isPlaceholderData, isError } = useQuery({
queryKey: ['sales'],
queryFn: fetchSales,
placeholderData: salesMock,
})
if (isError) return <SalesError />
return <Total value={data?.total} provisional={isPlaceholderData} />
That's three more lines, and the screen now has three honest states instead of a single, very confident one.
Other places where I see this happen:
- A
catchthat returns an empty array. The API goes down and the screen says "no orders found". The user concludes there are no orders. It's false information that looks good. - A success toast before the response. The button fires the
fetchand the toast appears on the same line. If the server returns a 500, the success message is already gone. - A fake progress bar. A
setIntervalthat climbs to 90% and waits. Everyone has done it, me included. On a 3-second upload, that's fine. On a 10-minute process, it becomes a promise with nothing behind it. - Status without a date. "All systems operational" with a green hardcoded in the source. If nobody measures it, that green is decoration.
Is useOptimistic a lie too?
That's the good objection. React 19 brought useOptimistic, a hook made to show the result before it exists. Isn't that exactly the problem?
In my view, no. The difference is that the assumption has a deadline and a way out:
const [likes, addOptimistic] = useOptimistic(
post.likes,
(current, delta: number) => current + delta,
)
function like() {
startTransition(async () => {
addOptimistic(1)
await likePost(post.id)
})
}
When the transition ends, the value goes back to whatever came from the real state. If the call fails and post.likes doesn't change, the number returns to the previous one. You still need to handle the error and tell the user, but the architecture already starts from the idea that the screen may be wrong for a moment.
The yardstick I use is the cost of being wrong. An optimistic like? Go ahead. If it fails, nobody loses anything. Payment, medical test, transfer, sending an invoice? Wait for the server to confirm. The user can handle a 2-second spinner. They can't handle finding out the next day that the bill was never generated.
What changes in your workflow
None of this requires a new library. It requires habit.
Model the states on purpose. Every component that depends on the network has at least loading, error, empty and success. "Empty" and "error" are different things, and the screen needs to treat them differently.
Lock mocks to the development environment. If a mock never needs to reach production, make the build fail when it shows up. MSW helps a lot here: the fake data lives in the network layer, outside the components, and you only turn on the worker in development.
A demo with fake data has to say it's fake. A "sample data" banner at the top solves it. Nobody confuses a Figma prototype with a product. A React prototype, with a deploy and a nice domain, fools everyone, including the director who's going to promise it to a customer on Friday.
Show the age of the data. An "updated 4 minutes ago" costs one line and changes how anyone reads a dashboard. TanStack Query already gives you dataUpdatedAt for free.
Test the bad path. Open DevTools, set the network to offline and click everything. Write a test with the API returning 500. If the screen keeps smiling, you found a bug.
The question I ask before deploying
Theranos is an extreme case, with real people receiving test results they couldn't trust. Nobody here is at that level, and you don't need to be to learn from it.
My opinion: a senior front-end dev cares about what the screen claims, not only how it looks. Before shipping, I ask: "if this number were wrong, would the interface let me notice?". If the answer is no, I go back to the code.
That's the standard I try to follow in my work. If you want to see how this looks in a real product, take a look at my projects.
LinkedIn summary
Elizabeth Holmes got 135 months in prison, and Theranos taught me something about React. According to the book Bad Blood, when the device failed during a demo, a fake result was sent remotely to look like it came from the machine. On screen, everything worked. Relax, I know the difference between fraud and a skeleton loader. But the mechanism is similar: a component draws a fake number with the same beautiful typography as a real one. A mock that survives all the way to production. A catch that returns an empty array and says "no orders found" when the API is down. A success toast before the server responds. It's almost never bad faith. It's haste. But your customer doesn't open the Network tab: if the screen says "saved", they believe it. Before every deploy, I ask myself: if this number were wrong, would the interface let me notice? I wrote about this on my blog, with code and the habits I adopted. What about you, have you ever caught a screen lying in your project? #React #Frontend #JavaScript #SoftwareDevelopment #Theranos