cd /news/artificial-intelligence/ai-writes-half-our-code-now-nobody-t… · home › topics › artificial-intelligence › article
[ARTICLE · art-160067] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

AI Writes Half Our Code Now. Nobody Taught Us How to Review It.

A developer, citing the State of AI 2026 survey of 7,258 developers, reports that AI now generates an average of 54% of respondents' code, up from 28% a year earlier, yet most engineers were trained to write code rather than review it. The writeup catalogs five recurring JavaScript and React bugs in AI-generated code—async callbacks inside forEach, missing await inside try/catch, comparator-less sort, and stale closures in useEffect—each verified by running the snippet, and pairs them with review rules to catch them.

by read5 min views2 publishedOct 29, 2026

AI wrote this function. It passed linting. It got approved. It shipped.

async function getUsers(ids) {
  const users = [];

  ids.forEach(async (id) => {
    const res = await fetch(`/api/users/${id}`);
    users.push(await res.json());
  });

  return users;
}

It returned an empty array. Every. Single. Time.

No error. No warning. Just [].

If you spotted it in 5 seconds, nice. If you didn't, you're not alone, and that's exactly the problem we want to talk about.

The State of AI 2026 developer survey collected answers from 7,258 developers, including how much of their code is AI-generated. The average answer was 54%. A year earlier, it was 28%.

(Fair caveat: an AI survey probably attracts people who use AI a lot. But even if the real number is lower, the direction is obvious.)

In one year, AI went from "helps with boilerplate" to "writes more than half the code."

But think about how most of us learned to code. We learned to write it. Tutorials, courses, bootcamps, LeetCode: almost all of it trains the writing muscle.

Almost nobody trained us to review code we didn't write, at speed, all day. And that's now the main job.

AI-generated code has a specific personality. It looks clean, it's confidently formatted, it has nice variable names, and it's wrong in subtle ways that don't throw errors.

Here are 5 bugs we see AI write over and over in JavaScript and React. Every snippet below has been run, and the output is real.

forEach doesn't wait for async That's our opening example. forEach calls your async callback, gets back a promise, and ignores it. It doesn't wait. So return users runs before a single fetch finishes.

What you get: []

The fix: use map to collect the promises, then Promise.all to wait for them.

async function getUsers(ids) {
  return Promise.all(
    ids.map(async (id) => {
      const res = await fetch(`/api/users/${id}`);
      return res.json();
    })
  );
}

🔍 Review rule: If you see async inside forEach, stop. It's almost always a bug.

try/catch that catches nothing

async function saveUser(user) {
  try {
    db.insert(user);
    return { ok: true };
  } catch (err) {
    console.error("Save failed:", err);
    return { ok: false };
  }
}

Looks safe, right? There's error handling and everything.

But db.insert() returns a promise, and there's no await. So the function returns { ok: true } immediately. When the insert fails later, the error is outside the try block. Your catch never runs.

What you get: { ok: true }, even when the save failed. The real error shows up as an unhandled promise rejection, which in modern Node.js crashes the process by default.

The fix: one word.

await db.insert(user);

🔍 Review rule: Any call that returns a promise inside a try block needs an await, or the catch is just decoration.

const prices = [100, 25, 9, 1200, 50];
prices.sort();

What you get: [100, 1200, 25, 50, 9]

By default, .sort() converts everything to strings and sorts alphabetically. "1200" comes before "25" because "1" comes before "2".

AI loves this one because it reads perfectly in plain English. "Sort the prices." Done. Except it isn't.

The fix:

prices.sort((a, b) => a - b);
// [9, 25, 50, 100, 1200]

🔍 Review rule: .sort() with no comparator on anything that isn't a plain string array is a red flag.

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setSeconds(seconds + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);

  return <p>{seconds}</p>;
}

It even cleans up the interval. Very responsible. Very wrong.

The empty dependency array means the effect runs once, so the interval callback captures seconds from the first render, when it was 0. Every tick sets it to 0 + 1.

What you get: 1. Forever.

The fix: use the functional updater so you always get the latest value.

setSeconds((s) => s + 1);

🔍 Review rule: A state variable used inside setInterval, setTimeout, or an event listener in a useEffect with [] deps? Check for a stale closure.

function TodoList() {
  const [todos, setTodos] = useState([]);

  function addTodo(text) {
    todos.push(text);
    setTodos(todos);
  }

  // ...
}

todos.push() mutates the existing array. Then setTodos(todos) passes React the same array reference. React compares the old and new state, sees they're the same object, and skips the re-render.

What you get: You click "Add". Nothing appears on screen.

The fix: create a new array.

setTodos([...todos, text]);

🔍 Review rule: .push(), .splice(), or direct property assignment on something that came from useState means the UI won't update.

Save this. Run through it every time AI hands you code.

await ed? Any catch actually catch what you think it catches?.sort(), ==, or parseInt) that might not do what the name suggests? useState being mutated directly?[], null, "", or 0? That last one matters most.

Here's our honest take.

Prompting is getting easier every month. The tools are getting better at understanding what you mean. That's great, but it also means prompting is becoming less of a differentiator.

What's getting more valuable is the thing AI is still bad at: knowing when the confident, clean, well-formatted code in front of you is wrong.

Every one of the bugs above:

You can only catch them if you actually understand how JavaScript and React work under the hood. Event loop. Closures. References. Promises.

The fundamentals didn't become less important when AI showed up. They became the whole job.

What's the sneakiest bug AI has ever shipped into your codebase?

Drop it in the comments. Bonus points for a snippet. Let's build the ultimate list of "AI code that looked fine."

If you want to go deeper on building with AI agents without losing your engineering skills, we cover exactly this in our Agentic Engineering Course.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @state of ai 2026 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/ai-writes-half-our-c…] indexed:0 read:5min 2026-10-29 · —