Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reactive Queries like useFindMany() do not refetch the data on input state change. #28

Open
joonshakya opened this issue Jun 19, 2024 · 7 comments

Comments

@joonshakya
Copy link

I was including a reactive state as an input in prisma's reactive query to be able to filter users of a specific type from the database.
Even after the useState value changes the data is not fetched with the new input.

Minimal example:

import { Text, TouchableOpacity } from "react-native";
import { prisma } from "../db/prisma";
import { useState } from "react";
import { UserTypeChoice } from "../config/enums";

export default function UsersScreen() {
  const [userType, setUserType] = useState<UserTypeChoice>(
    UserTypeChoice.PARTICIPANT
  );

  const users = prisma.user.useFindMany({
    where: {
      type: userType,
    },
  });

  return (
    <>
      <Text>Users: {users.length}</Text>
      <TouchableOpacity
        onPress={() => {
          setUserType(UserTypeChoice.ORGANIZER);
        }}
      >
        <Text>Organizers</Text>
      </TouchableOpacity>
    </>
  );
}
@sorenbs
Copy link
Member

sorenbs commented Jul 6, 2024

Thank you for reporting this @joonshakya! This is the kind of feedback we are looking for during the preview phase.

There are a few different ways we can handle this.

One approach is to let Prisma take responsibility of the view state as well as the actual app state. I took that approach in this demo app. You can see that addTransactionView is a Prisma model rather than stored with useState: https://github.com/sorenbs/budget-buddy-expo/blob/main/components/AddTransaction.tsx

That's pretty heavy handed though. Perhaps we can make it much simpler to tell Prisma to handle this kind of transient state.

The other approach is to make Prisma aware of relevant useState use. Perhaps a syntax like this:

const [userType, setUserType] = prisma.$watch(useState<UserTypeChoice>(
    UserTypeChoice.PARTICIPANT
  ));

Or perhaps more simply, something like this:

const users = prisma.user.useFindMany({
    where: {
      type: userType,
    },
  }, [userType]);

Do you have any preferences?

CC @betomoedano who also asked about this.

@dwightwatson
Copy link
Contributor

I think passing an array of dependencies feels a lot more natural in React than wrapping useState.

@betomoedano
Copy link

betomoedano commented Jul 7, 2024

I agree with @dwightwatson ☝️

Although, I wonder if we can manage these dependencies internally so that the user does not need to provide the array. In other words, treating the query as a variable that can change. Not only can it change a field but also a property of the query, for example:

const [orderBy, setOrderBy] 
useState<Prisma.NotionFileOrderByWithRelationInput>({ order: "asc" });

const files = extendedClient.notionFile.useFindMany({
  where: { parentFile: { is: null } }, 
  orderBy: orderBy, // property and value will change
});

// Any of these state updates should trigger a re-fetch
setOrderBy({ order: "asc" });
setOrderBy({ createdAt: "desc" });

We also need to prevent re-fetching if query hasn't changed.

@ovidb
Copy link

ovidb commented Jul 7, 2024

I also agree with @dwightwatson.

Dependency array makes more sense and, implementation wise, is probably easier compared to determining when to re-run the query based on the query inputs.

DX would be so much nicer if Prisma could do the heavy lifting but deps is a good start.

@mathieupost
Copy link

This would be great to add!

Unfortunately I can't seem to get using prisma for the state to work with orderBy using this:

  const settings = prisma.settings.useFindFirst();
  const assets = prisma.asset.useFindMany({
    orderBy: {
      creationTime: settings?.sortOrder === "creationTime.asc" ? "asc" : "desc",
    },
  });

@Sofronijev
Copy link

Having an identical issue, it would be great if this is added. Besides adding an dependency array it would also be nice if we have a prop like refetchOnArgsChange, similar to redux toolkit, might be easier than passing all the dependencies.

@Sofronijev
Copy link

Tried to solve the issue with reactiveQueriesExtension but had the same result. Trying to make some budget app with different wallets, changing the wallet id doesn't update the query.

export const queriesPrisma = baseClient.$extends(reactiveQueriesExtension());

const getTransactions = (wallet_id: number, take?: number) => {
    queriesPrisma.transactions.findMany(
      (data) => {
        setData(data);
      },
      {
        take,
        orderBy: { date: "desc" },
        where: { wallet_id: wallet_id },
      }
    );
  };
  
 useEffect(() => {
    if (activeWallet?.walletId) {
      getTransactions(activeWallet.walletId, 5);
    }
  }, [activeWallet?.walletId]);

It just reruns the same query that run initially even if the wallet_id changes.

It work if I do it like this, but then it doesn't refetch when item is deleted while previous example does.

  export const hooksPrisma = baseClient.$extends(reactiveHooksExtension());

  const getTransactions = async (wallet_id: number, take?: number) => {
    await hooksPrisma.transactions
      .findMany({
        take: take,
        orderBy: { date: "desc" },
        where: { wallet_id: wallet_id },
      })
      .then((data) => setData(data));
  };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants