#Make db modifications on loader function and apply immediately (preload?)

1 messages · Page 1 of 1 (latest)

tawdry basalt
#

My loader

export async function loader({ request, params }: LoaderArgs) {
  invariant(params.menuId, "expected params.menuId")
  invariant(params.tableId, "expected params.menuId")
  invariant(params.branchId, "expected params.menuId")

  const { branchId, tableId, menuId } = params
  let menuCategories = await getMenuCategories(menuId)
  let userId = await getUserId(request)
  const session = await getSession(request)
  let userColor = await session.get("userColor")

  // CART
  let order = await createOrGetOrder(branchId, tableId)
  let orderId = await getOrderId(tableId)

  //~~> if not user session create <~~//
  try {
    await connectUserSessionToDb(
      branchId,
      userId,
      orderId ? orderId.id : "",
      userColor
    )
  } catch (e) {
    console.error(e)
  }

  let cartItemsActive = await db.cartItem.findMany({
    where: { orderId: orderId.id, activeOnOrder: true },
    include: { menuItem: true },
    orderBy: {
      id: "asc",
    },
  })
  let cartItemsNotActive = await db.cartItem.findMany({
    where: { orderId: orderId.id, activeOnOrder: false, userId: userId },
    include: { menuItem: true },
    orderBy: {
      id: "asc",
    },
  })

  const subtotal =
    Array.isArray(order) && order.length > 0
      ? order.reduce((acc, item) => acc + item.price * item.quantity, 0)
      : undefined

  const waitress = await getWaitress(tableId)

  let waitressList = waitress?.map((a) => a.employee)

  let data = {
    menuCategories,
    waitress,
    order,
    subtotal,
    branchId,
    tableId,
    cartItemsActive,
    cartItemsNotActive,
    userColor,
  }

  return json({ data })
}
stable steeple
#

You should never perform mutations in a loader

#

Instead perform these in an action

tawdry basalt
#

but the click on the Link doesnt perform any action on action function

stable steeple
#

If you are writing to the DB, it should go into an action

#

You can call the action from JS outside of a form submission if needed

tawdry basalt
#

How?

stable steeple
#

But you don't have to use this, you can replace your link with a form

tawdry basalt
#

Its the convention? because i dont need any form on going to another route

stable steeple
#

Then the page will still work with JS disabled

stable steeple
#

But also semantically you should never perform writes to the database in a loader

tawdry basalt
#
   <LargeButtonWithIcon
            to={`/branch/${branch.id}/table/${tableId}/menu/${menuType.id}`}
            title="Ver Menu"
            
          />
        ) : (
          <p className="py-4 px-4">{errors}</p>
        )}
stable steeple
#

Because loaders can be called at any time

tawdry basalt
#

This is my button that goes to the route

#

so inside this button i insert a Form? and add this request to action?

stable steeple
#

Forms go around submit buttons

tawdry basalt
#

Im sorry thats where im a little confused, this is not a submit button, its just a Link button to go to another route

stable steeple
#

You have the logic backwards, if this an action by the user that performs a write on the database you shouldn't do it in a loader

#

It needs to go in an action

#

And the way we call actions is with forms (or useSubmit)

tawdry basalt
#

I understand that, thank you. But when the user clicks on link, it doesnt perform any post

#

so i use submit

stable steeple
#

Yep, so you replace the link with a <form><button> combo

tawdry basalt
#

then on action if(submit) redirect to "etc" and perform the action

#

So what links its only usefull when i want to go to another website thats all

#

route*

stable steeple
#

Perform the mutation first (in the action) then redirect to the appropriate url

tawdry basalt
#

let me try that

stable steeple
#

this is similar to how you would handle a logout button/link in remix

#

here they're defining a separate resource route, this is only needed if you need to call your action from a different route to what you're rendering. also if you already have an action in your route, you may want a separate one so you don't have to identify them in the action

"the one route, one action" vs "one route, many action" is a developer choice mostly

tawdry basalt
#

thanksdamn

#

i did that, but keep getting the same error

#
        // />
          <Form method="post">
            <button type="submit" name="connectUser" value="connect">
              go
            </button>
          </Form>
#

on action


  if (goMenu === "connect") {
    try {
      await connectUserSessionToDb(
        branchId,
        userId,
        orderId ? orderId.id : "",
        userColor
      )
      return redirect(
        `/branch/${branchId}/table/${tableId}/menu/${menuType.id}`
      )
    } catch (e) {
      console.error(e)
    }
  }
#

it redirects perfectly to my menu, but when i try to add some item on my database i got the same error

#
 An operation failed because it depends on one or more records that were required but not found. No 'User' record(s) (needed to inline the relation on 'CartItem' record(s)) was found for a nested connect on one-to-many relation 'CartItemToUser'.
#

that means the user its not connected to the db

#

on prisma studio says its connected, but i need to still refresh it @stable steeple