Next.js Discord

Discord Forum

nextjs tanstack react query issue

Answered
Crazy ant posted this in #help-forum
Open in Discord
Avatar
Crazy antOP
I have a react tanstack table where I have listed all items and when I want to go to particular item detail, I need to click on Action as below
when I check console log of "id" in editor, every time I find that previous item's id is also logged in the console along with current item's id.
I am confused where it went wrong. I need to see only the particular item's id on which I clicked.
columnHelper.accessor('_id', { cell: row => ( <div className="flex gap-4"> <Editor id={row.getValue()} /> </div> ), header: () => <span>Action</span>, }),

Editor ->

export default function Editor({id}) { console.log(id) const [open, setOpen] = useState(false) const handleDialogChange = () => { setOpen(!open) } return( <Dialog open={open} onOpenChange={handleDialogChange}> <DialogTrigger asChild> <Button variant="outline" className="item-container> Browse </Button> </DialogTrigger> <DialogContent className="item-content"> <DialogHeader className="items-center justify-center"> <DialogTitle className="action-caption"> Item </DialogTitle> </DialogHeader> ..................................................... ................................................... </DialogContent> </Dialog > ) }
Answered by necm1
you're welcome
View full answer

48 Replies

Avatar
Hi! If you log your state too, you might find out that previous id and open = false
Current id and open = true
Avatar
Crazy antOP
@Julienng , Its true, But how to get currentId . because all other id's are also fetched. How to differentiate.Actually I dont want to use UseEffect and UseCallback since the html content is inside a dialog.
Avatar
What do you mean by "all other id's are also fetched"
if you opened a dialog and close it
and try to open another one, you'll still have the old id
you could create a new state like
const [currentId, setCurrentId] = useState(id);

useEffect(() => {
  setCurrentId(id)
}, [id]);
and it doesn't matter if there is html content inside the dialog
and one thing
I'm sure that you're using radix-ui / shadcn dialog component;

why do you've a <DialogTrigger> and also a state for open
Avatar
Crazy antOP
I resolved This let me explain
Avatar
Crazy antOP
I do not use useState etc because this makes a messup for me as if I need more states I have to maintain many useState's and code will be long. Inseatd if require I use useReducer. In this case I have done below tricks which saves me to write additional lines to-> Insead of normal fetch , I used tanstack query to fetch items from backend but in the useQuery I just put a condition to fech query if only dialog is opened. Actually the scenario was since I was just pushing id like below <Editor id={row.getValue()} /> all id's are automaticlly coming from data tables. So I need to fetch only the item id for which dialog is opened. So I justed use tanstack query and put a boolean condition in it.
Avatar
so, just making things clear
1. You fetch the data and show the table (including the fetched data)
2. You use useQuery when the your Dialog opens, to get the data based of the passed id?
I would not bound the <Editor /> to every result of your table
Avatar
Crazy antOP
yes
Avatar
YourTable.tsx
const [openDialog, setOpenDialog] = useState(false);

/*....*/
// your cell
cell: row => (
          <div className="flex gap-4">
            <Button variant="outline" className="item-container" onClick={() => setOpenDialog(true)}>Browse</Button>
          </div>
        )



return (
  <>
    // TABLE ETC....
    <Editor open={openDialog} onOpenChange={(value: boolean) => setOpenDialog(false)}  />
  </>
)


Editor.tsx
export default function Editor({id, open: passedOpen, onOpenChange}: {id: string | null, open: boolean, onOpenChange: (value: boolean) => void}) {
  const [open, setOpen] = useState(false);
  
  const handleOpenChange = (value: boolean) => {
    setOpen(false);
    onOpenChange(false);
  }

  return <Dialog open={open} onOpenChange={(value: boolean) => setEditorDialogOpen()}>
    <DialogContent>
      // stuff here without DialogTrigger
    </DialogContent>
  </Dialog>
}
Avatar
Crazy antOP
@necm1 , I used tenstack data table. I am redirecting to editor from columns array . If I would use normal react component , I would not also bound the <Editor /> to every result of your table
Avatar
so you would simply have one instance of the Editor component
Avatar
Crazy antOP
@necm1 , Thanks for your reply, I will try your code to implement and let you know
Avatar
just let me know if you need help
Avatar
Crazy antOP
@necm1 , Here onOpenChange is a function not a boolean value . Then in handleChange function how do you change its state const handleOpenChange = (value: boolean) => { setOpen(false); onOpenChange(false); }
Ok you are passing it as a props
Avatar
yes
just passing the state of the Dialog back to the ParentComponent
so you can update the state in the ParentComponent
Avatar
Crazy antOP
Got it. Thanks @necm1 . It helped me.
Avatar
maybe with this approach, you wouldn't need to use useQuery at all
but you would have to pass the id like this then
Avatar
Crazy antOP
Yes , with this approach I do not have to put any condition to useQuery. But howver I need to fetch items detail for this id.
Avatar
ParentComponent.tsx:

const [openDialog, setOpenDialog] = useState(false);
const [currentId, setCurrentId] = useState<string | null>(null);

/*....*/
// your cell
cell: row => (
          <div className="flex gap-4">
            <Button
              variant="outline" 
              className="item-container" 
              onClick={() => {
                setCurrentId(row.getValue());
                setOpenDialog(true)
              }}
            >Browse</Button>
          </div>
        )

return (
  <>
    // TABLE ETC....
    <Editor id={currentId} open={openDialog} onOpenChange={(value: boolean) => setOpenDialog(false)}  />
  </>
)
so just the parent will tkae care of the id including the state
don't you already have the data of the id trough the fetching? or do you just fetched the id?
Avatar
Crazy antOP
no I do not have individual data. What I have in paranet component its items array. When I am clicking on a item from the table it must show the particular item detail. In a normal table component I would to below approach-> items.map((item)=>(<Table>.....<Table>) from here I would push the whole item to the editor. In this case I do not need to fetch the item again with its id. But tanstack react table is different-> parent component:-> <DataTable columns={itemColumns} items={items} /> in columns:-> columnHelper.accessor('_id', { cell: row => ( <div className="flex gap-4"> <Editor id={row.getValue()} /> </div> ), header: () => <span>Action</span>, }), So I am not sure How do I push each whole item from this column. That's why I needed to fetch item based on its id.
Avatar
its easy
so
basically
Avatar
Crazy antOP
@necm1 , Could you please advise me how
Avatar
if you want to send the whole row data
Avatar
Crazy antOP
yes
Avatar
just simply do this:

cell: (cell) => {
  const row = cell.row.original;
  console.log(row); // all data from the current row

  return (
    <div className="flex gap-4">
      <Button
        variant="outline" 
        className="item-container" 
        onClick={() => {
          setCurrentItem(row);
          setOpenDialog(true)
        }}
      >Browse</Button>
    </div>
 );
}
Avatar
Crazy antOP
oh! Thanks . Just I need to push row. ok
Thank you so much @necm1 and all .
Avatar
but yea, don't forget to refactor your <Editor> props and the state
Avatar
you're welcome
Answer
Avatar
Crazy antOP
Ya that i will do in <Editor/>
Thank you @necm1
Avatar
if you face issues, feel free to reopen this thread and mention me
Avatar
Crazy antOP
@necm1 , Thanks for your help. Now I modified the attached code . You can open it in any code editor. Its working but I am not satisfied with the code because in Editor I had to use useEffect since I required to show the currentItem when dialog is open. As per my opinion the code is not perfect since all other items also pushed into the editor, it only shows the current item when dialogue is opened. I am not sure whether this approach is good for bulk 1000 items during traffic, or we need to fetch individual item from database by its id when the dialogue is open.Please let me know your opinion.
Image