Repository: next.js
Issue: Client components fail to use server actions to mutate server data
Labels: bug,Lazy Loading

### Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/next-js-server-action-issue-lxjtkg

### To Reproduce

This is a demo that use buttons (client components) to call server actions (from `actions.ts`) to mutate server-side data array (in `data.ts`).

<img width="1437" alt="image" src="https://github.com/vercel/next.js/assets/36685998/f8288fd3-cc8a-4fd9-b11d-a2b07d44f1c0">

Steps:
1. Enter the `app/page.tsx` source.
2. Find `<Nop />`. It is a patch server component I wrote, which only calls a do-nothing server action `nop()` from `actions.ts`. Firstly keep it **commented out**.
3. Try to click buttons. You will see no UI updates.
4. Check server console logs to see array length changes, but the page UI does not. If removing an item after it gets empty, an error is raised. It seems like mutating an invisible copied array.
5.  Now **uncomment** `<Nop />`, and again try the buttons. You will see they work magically with UI updates.

Relevant code:

```typescript
// page.tsx
import Nop from "./ui/server-nop";
import { AddItemClient, RemoveItemClient } from "./ui/client-components";
import { fetchItems } from "./lib/data";

export default async function Home() {
  const data_array = await fetchItems();
  return (
    <>
      {/* comment / uncomment the following line */}
      {/* <Nop /> */}
      ...
      <AddItemClient />
      <RemoveItemClient />
      <p>
        Array length: <span>{data_array.length}</span>
      </p>
      <ul>{data_array?.map((item) => <li key={item.id}>{item.value}</li>)}</ul>
      ...
    </>
  );
}
```

```typescript
// Nop component
import { nop } from "../lib/actions";

export default function Nop() {
  nop();
  return <></>;
}
```

```typescript
// client buttons
"use client";

import { createItem, deleteItem } from "../lib/actions";

export function AddItemClient() {
  return (
    <form action={createItem}>
      <button type="submit">Add Item (Client Component)</button>
    </form>
  );
}

export function RemoveItemClient() {
  return (
    <form action={deleteItem}>
      <button type="submit">Remove Item (Client Component)</button>
    </form>
  );
}
```

```typescript
// actions.ts
"use server";

import { data_in_memory } from "./data";
import { revalidatePath } from "next/cache";

export async function nop() {}

export async function createItem() {
  const length_before = data_in_memory.length;
  data_in_memory.push({
    id: "23",
    value: "item (added)",
  });
  const length_after = data_in_memory.length;
  console.log(`createItem: array length ${length_before} -> ${length_after}`);
  revalidatePath("/");
}

export async function deleteItem() {
  const length_before = data_in_memory.length;
  if (data_in_memory.length === 0) {
    throw new Error("Cannot remove item from empty array!");
  }
  data_in_memory.pop();
  const length_after = data_in_memory.length;
  console.log(`deleteItem: array length ${length_before} -> ${length_after}`);
  revalidatePath("/");
}
```

```typescript
// data.ts
export const data_in_memory = [
  {
    id: "1",
    value: "item 1",
  },
  {
    id: "2",
    value: "item 2",
  },
];

export async function fetchItems() {
  return data_in_memory;
}
```

### Current vs. Expected behavior

Current: 
- Without `<Nop />` in `page.tsx`: clicking buttons will not update the UI, and will modify an invisible array on server (which can be verified through server log, or clicking remove button multiple times to see an error of empty array).
- With `<Nop />` in `page.tsx`: the buttons work as magic.

Expected: with or without the patch component `<Nop />`, clicking the buttons (client components) should correctly add or remove items of the correct server-side data array, and the page UI should be updated accordingly.

### Verify canary release

- [x] I verified that the issue exists in the latest Next.js canary release

### Provide environment information

```bash
Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 14.0.5-canary.41
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.1.3
Next.js Config:
  output: N/A
```


### Which area(s) are affected? (Select all that apply)

Not sure, Dynamic imports (next/dynamic)

### Which stage(s) are affected? (Select all that apply)

next dev (local), next start (local)

### Additional context

Observations:
- We need a server component (like `<Nop />`) to actually import something from the server action file (actions.ts) to make client components have access to the right data array in server's memory.
- If not, client components will issue server actions that add to or remove from a **copy** of the data array, instead of the original array.

My temp solution: patch such a nop server component that imports from the server action file; or pass the server action as prop to client components.