Ad

Why Callback Function In React-dnd UseDrop Hook Can't Update Parent Component State?

- 1 answer

dnd Hook Api, and want to call parent component callback function to update state in useDrop drop function, however I can only update the parent state from init state.

Here is an example, no matter how I drop the div to the dropTarget, the count is always update to 1, but when click button, it can update as I expected, why is this happen? and how to fix that?

https://codesandbox.io/s/reactdndexample3-gpc61?fontsize=14

import React, { useState } from 'react';
import { __EXPERIMENTAL_DND_HOOKS_THAT_MAY_CHANGE_AND_BREAK_MY_BUILD__ as dnd, DropTarget } from 'react-dnd'
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend'
const { useDrag,useDrop } = dnd

function HookTest(props) {
  const [count,setCount] = useState(0);

  return (
    <div>
      <button onClick={()=>{setCount(count + 1)}}>clickToAdd</button>
      <DropDiv addCount={()=>{setCount(count + 1)}}></DropDiv>
      <DragDiv></DragDiv>
      <div>{count}</div>
    </div>
  );
}

export default DragDropContext(HTML5Backend)(HookTest)

function DropDiv(props) {
  const [collectedProps, drop] = useDrop({
    accept:"widget",
    hover:(item,monitor) => {
    },
    drop:(item,monitor)=>props.addCount(),
    collect:(monitor) => {
      return {
        isOver:monitor.isOver({shallow: true}),
      }
    }
  })
  return (
        <div ref={drop} style={{width:"100px",height:"100px",background:"blue"}}>
            dropTarget
        </div>
    )
}

function DragDiv(props) {
  const [dragSource,drag] = useDrag({
    item: {type:"widget"},
        collect: monitor => ({
            opacity: monitor.isDragging() ? 0.4 : 1,
        }),
  })

  return (
        <div ref={drag} style={{width:"100px",height:"100px",background:"red"}}>
            DragSource
        </div>
    )
}
Ad

Answer

The update does not work because in the context of the created functions for onClick und addCount, count has always the value 0.

I recommend you use the alternate syntax of setCount and pass a function which gets the previous state as an argument and returns the updated state.

<button onClick={()=>{setCount(prevCount => prevCount + 1)}}>clickToAdd</button>
<DropDiv addCount={()=>{setCount(prevCount => prevCount + 1)}}></DropDiv>

Working example

Ad
source: stackoverflow.com
Ad