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

vike-react-telefunc #131

Open
nitedani opened this issue Jul 12, 2024 · 2 comments
Open

vike-react-telefunc #131

nitedani opened this issue Jul 12, 2024 · 2 comments

Comments

@nitedani
Copy link
Member

Ideas for vike-react-telefunc

Right now, to integrate telefunc and @tanstack/react-query, we need to write some boilerplate for query invalidation:

// fruits.telefunc.ts
const db = [
  {
    id: 1,
    name: "Apple",
  },
  {
    id: 2,
    name: "Orange",
  },
];

export async function addFruit(fruit: { id: number; name: string }) {
  db.push(fruit);
}

export async function updateFruit(input: { id: number; name: string }) {
  const fruit = db.find((fruit) => fruit.id === input.id);
  if (fruit) {
    fruit.name = input.name;
  }
  return fruit;
}

export async function getFruit(id: number) {
  return db.find((fruit) => fruit.id === id);
}

export async function getFruits() {
  return db;
}
// +Page.tsx

import {
  useSuspenseQuery,
  useMutation,
  useQueryClient,
} from "@tanstack/react-query";
import { getFruits, getFruit, addFruit, updateFruit } from "./fruits.telefunc";

const useFruits = () =>
  useSuspenseQuery({
    queryFn: getFruits,
    queryKey: ["fruits"],
  });

const useFruit = (id: number) =>
  useSuspenseQuery({
    queryFn: () => getFruit(id),
    queryKey: ["fruits", id],
  });

const useAddFruit = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: addFruit,
    onSettled() {
      queryClient.invalidateQueries({ queryKey: ["fruits"] });
    },
  });
};

const useUpdateFruit = () => {
  const queryClient = useQueryClient();
  return useMutation({
    mutationFn: updateFruit,
    onSettled() {
      queryClient.invalidateQueries({ queryKey: ["fruits"] });
    },
  });
};

It would be nice, if this integration could be simplified, for example:

// fruits.telefunc.ts

import { invalidates } from "vike-react-telefunc"

const db = [
  {
    id: 1,
    name: "Apple",
  },
  {
    id: 2,
    name: "Orange",
  },
];

invalidates(getFruits);
invalidates(getFruit); // invalidates all getFruit queries
export async function addFruit(fruit: { id: number; name: string }) {
  db.push(fruit);
}

invalidates((input) => [getFruit, input.id]); // invalidates a single getFruit query
export async function updateFruit(input: { id: number; name: string }) {
  const fruit = db.find((fruit) => fruit.id === input.id);
  if (fruit) {
    fruit.name = input.name;
  }
  return fruit;
}

// queryKey: ['/src/pages/index/fruits.telefunc.ts:getFruit', id]
export async function getFruit(id: number) {
  return db.find((fruit) => fruit.id === id);
}

// queryKey: ['/src/pages/index/fruits.telefunc.ts:getFruits']
export async function getFruits() {
  return db;
}
//+Page.tsx

import { useQuery, useMutation } from "vike-react-telefunc";
import { getFruits, getFruit, addFruit, updateFruit } from "./fruits.telefunc";

const useFruits = () => useQuery(getFruits);
const useFruit = (id: number) => useQuery(getFruit, id);
const useAddFruit = () => useMutation(addFruit);
const useUpdateFruit = () => useMutation(updateFruit);

What do you think?

@brillout
Copy link
Member

brillout commented Jul 13, 2024

Yes, that would be wonderful.

How about something like this?

cache(getFruits, ['fruits'])
export async function addFruit(fruit: { id: number; name: string }) {
  db.push(fruit);
}

cache(updateFruit, input => ['fruit', input.id])
export async function updateFruit(input: { id: number; name: string }) {
  const fruit = db.find((fruit) => fruit.id === input.id);
  if (fruit) {
    fruit.name = input.name;
  }
  return fruit;
}

cache(getFruit, input => ['fruit', input.id])
export async function getFruit(id: number) {
  return db.find((fruit) => fruit.id === id);
}

cache(getFruits, ['fruits'])
export async function getFruits() {
  return db;
}

The cache is invalidated when useMutation() is used.

I feel like invalidating over a cache key is more robust than directly invalidating telefunctions? It's also more TanStack Query idiomatic I think?

Also, maybe we can name it vike-react-telefunc-query for now (I want to experiment with a separate extension that doesn't use TanStack Query). I'm not sure yet which one will end up being the main extension. (Ideally, we can have a single vike-react-telefunc with an optional features/peer dependency with vike-react-query, but I don't know how feasible that is.)

@brillout
Copy link
Member

(Maybe we shouldn't name it cache() but key() or queryKey() to better align with TanStack Query.)

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

No branches or pull requests

2 participants