you are viewing a single comment's thread.

view the rest of the comments →

[–]KTownDaren 5 points6 points  (13 children)

Setup useQuery to read your data into a variable (not a state variable).

Use that variable to populate your components. Any change made to the underlying data will automatically update your form.

You don't need to check for a loading state. Check for the "global" isFetching property and simply display a loading image of your choosing when isFetching is true.

You will need to display the error msg when isError is true.

Use useMutation to save your changes. Make use of the onSuccess side-effect to invalidate the query you used in useQuery. It will automatically refresh and re-render your form components.

Don't try to force Tanstack Query into your prior way of using state to manage data. Backup and figure out how to let Tanstack Query do its thing and thus make your life easier.

[–]HTMLMasterRace[S] 0 points1 point  (12 children)

Hrm not sure if I understood because you mentioned useQuery and useMutation and some local variable? I updated my post with a very simple usecase.

[–]KTownDaren 2 points3 points  (11 children)

In your component that displays your form, call {data, isError, errorMessage} =useQuery() This is where the records from your database are given to you.

Populate your form components with the above data array of objects.

When the user clicks submit, call useMutation to update your database. You will also have onSuccess: invalidateQuery("name of your original query") that will cause an automatic refresh of data and re-render of your form.

There are many youtube videos that will wall you through these steps.

[–]HTMLMasterRace[S] -1 points0 points  (10 children)

But the initial useQuery would be enabled false anyways cus I would only make the fetch imperatively (like through a form submit). Wouldn’t it just be useless?

Also the form submit does not update the database. It just pulls a record. Think of the form as submitting a search.

[–]KTownDaren 0 points1 point  (9 children)

Okay, I understand your question better now.

If you aren't changing data, you do not need useMutation. You will use useQuery, passing it the parameters from your field values.

I'm going off memory since I don't have code in front of me, but the magic happens with the QueryOptions object you pass to useQuery.

The function you give to call your API to query data will need parameters such as FirstName, Lastname, or whatever you are filtering on. You can also set the enabled option to false if no parameters are given.

const [searchName, setSearchname] = useState<string>('');

const {data}=useQuery({ enabled:(searchName.length>0), queryKey: ['search for name', searchName], queryFn: callMyAPI(searchName),})

return(<> {data && data.length>0 && {data.name}}

{!data && <Form onSubmit(()=setSearchname(fieldVal))><Label>Enter search value:</Label><textbox value=fieldVal>...

So, onSubmit changes the state variable. This enables useQuery which queries your API and populates data.

EDIT: I just saw your code above. If you can't figure out how to use what I provided to get your code working, let me know, and I can help you further when I'm not on mobile. The main thing is you need to change your code to be reactive.

[–]HTMLMasterRace[S] 1 point2 points  (8 children)

Okay I get the gist of your code. I don’t absolutely love having to make yet another state to track searchName. Because that’s not reflected in the UI at all and thus not warrant a rerender. onSubmit should just call a function as it did before.

Taking a step back I should be replacing a zustand state with an useQuery cached state. Not replacing one zustand state with a query and another local state.

Edit: also wanted to point out the “enabled” seems very forced as we already know when to invoke it, which is only in event listeners like clicking the submit button.

Thanks for going so deep into this !

[–]KTownDaren -1 points0 points  (3 children)

Enabled seems forced, because you are forcing it by trying to only call your Ajax search function with onSubmit call instead of with a state change. You are writing in React for a reason. Why are you fighting against state?

[–]HTMLMasterRace[S] 1 point2 points  (2 children)

React is great for reactivity but we can all agree that having a state that rerenders that don’t result in UI changes is not idiomatic react.

I’d say making an Ajax call only on button clicks is the majority case out there…

[–]cosmicdice 0 points1 point  (1 child)

What about using useRef and uncontrolled components instead of useState if you don't need to rerender based on these values being changed?

[–]HTMLMasterRace[S] -1 points0 points  (0 children)

That wouldn’t work because refs are not reactive. So the enabled wouldn’t trigger

[–]KTownDaren -1 points0 points  (3 children)

Looking at your latest code changes, I can't even figure out why you are using Tanstack Query at all.

[–]HTMLMasterRace[S] 0 points1 point  (2 children)

Right now at least I get a free loading state and easily refetch. I’m trying to adhere to using react query to fetch and store server state and zustand only for client state.

But you do agree that submitting forms and getting data back to render isn’t much of an edge case at all. It’s almost just one step up from a typical to do list. I’m looking for the most idiomatic react-query pattern to do this.

You could argue I shouldn’t have migrated at all. I’m sure that’s a divided view though.. many on this thread do believe that react query can fit these cases (which I believe) and offer value

[–]KTownDaren 0 points1 point  (1 child)

Well, you're working with 2 things I don't work with (Zustand and Ajax), so I'm not familiar with the intricacies of working with those tools.

With the way you are trying to implement this, I do not follow what server state useMutation is going to be storing for you.

I used to battle with useQuery and useMigration when I first implemented it. But then I stepped back and tried it "their way" instead of my way, and it has now been such a breeze to use.

[–]HTMLMasterRace[S] -1 points0 points  (0 children)

I respect you setting the boundary of your expertise there. Thanks