# Call an action from a loader in Remix

Used: @remix-run/node@2.0.0, @remix-run/cloudflare@2.0.0, and @remix-run/deno@2.0.0

Let's say you have a route with an action, and now you want a route loader to call that action. The simplest way would be to move the code in the action to a different function and call it in both places:

```ts {% path="app/routes/something.ts" %}
async function doSomething() { /* code */ }

export async function loader(args: LoaderFunctionArgs) {
  // some code
  await doSomething()
  // more code
}

export async function action(args: ActionFunctionArgs) {
  // some code
  await doSomething()
  // more code
}
```

This way, the `doSomething` function can receive exactly the arguments it needs and return values instead of responses which gives you more flexibility when using it.

Another option is to call the action:

```ts {% path="app/routes/something.ts" %}
export async function action(args: ActionFunctionArgs) { /* some code */ }

export async function loader({ request, params, context }: LoaderFunctionArgs) {
  let body = new FormData()
  // add values to body here

  let actionResponse = await action({
    request: new Request(request.url, { method: "post", headers: request.headers, body }),
    params,
    context,
  })

  let actionData = await actionResponse.json()

  // more code using actionData here
}
```

And finally another option is to do a fetch to the action:

```ts {% path="app/routes/something.ts" %}
export async function action(args: ActionFunctionArgs) { /* some code */ }

export async function loader({ request, params, context }: LoaderFunctionArgs) {
  let actionResponse = await fetch(request.url, { method: "POST", headers })
  // more code using actionResponse here
}
```

In all cases where I used `request.url` that's supposing the action is on the same URL, but if it's in a different URL you can do.

```ts
let url = new URL("/some/pathname", request.url);
```

And this way change the pathname while retaining the hostname and protocol.