react dnd-kit draggable doesn't get dropped onto droppable

86 Views Asked by At

I'm new to react and I'm doing a project that involves simulating a quantum computer. In our simulator we want to be able to drag gates from a toolbar and drop them onto "qubit lines". How do I do that?

Here's the code

import './App.css';
import React, { useState, ReactNode, useEffect, useMemo} from 'react';
import './components/circuitboard.css';
import axios from 'axios';
import './components/toolbar.css';
import {Gate} from './components/gate';
import {DndContext, useDroppable} from '@dnd-kit/core';
import {
  createSnapModifier,
  restrictToHorizontalAxis,
} from '@dnd-kit/modifiers';

function Toolbar() {
    const gateX = <Gate name="X"/>;
    const gateY = <Gate name="Y"/>;
    const gateZ = <Gate name="Z"/>;
    const gateH = <Gate name="H"/>;

    return (
      <div className="toolbar">
        <section className="gate-container">
          {gateH}
            {gateX}
            {gateY}
            {gateZ}
        </section>
      </div>
    );

    
  }

function Circuitboard() {
  const [qubitLines, setQubitLines] = useState<ReactNode[]>([]);
  const [circuit, setCircuit] = useState([["H"]]);
  const [states, setStates] = useState("");
  const {isOver, setNodeRef} = useDroppable({
    id: "droppable",
    data: {
      accepts:['gate'],
    }
  });
  const style = {
    opacity: isOver ? 1 : 0.5,
  };

  useEffect(() => {
    // Initialize ketLines with three elements when the component mounts
    setQubitLines([
        <div className="qubit-line" data-testid="qubit-line" key={0}>
        <p>|0⟩</p><hr/>
        </div>,
        <div className="qubit-line" data-testid="qubit-line" key={1}>
          <p>|0⟩</p><hr/>
        </div>,
        <div className="qubit-line" data-testid="qubit-line" key={2}>
          <p>|0⟩</p><hr/>
        </div>
    ]);
  }, []); // Empty dependency array to ensure this effect runs only once, on mount

  const addQubit = () => {
    if (qubitLines.length < 10) {
      setQubitLines(prevQubitLines => [
        ...prevQubitLines,
        <div className="qubit-line" data-testid="qubit-line" key={prevQubitLines.length}>
          <p>|0⟩</p><hr/>
        </div>
      ]);
    }
    else {
      alert("No more qubits can be added");
      console.log("No more qubits can be added");
    }
  };

  const removeQubit = () => {
    if (qubitLines.length > 0) {
      setQubitLines(prevQubitLines => prevQubitLines.slice(0, -1));
    }
    else {
      //TODO make this a visible error
      console.log("Already 0 qubits");
    }
  };

  //const axios = require('axios');

  async function ping() {
    const response = await axios.post('http://localhost:8000/ping', {
          message: "ping"

  })
  .then(function(response: any){
    console.log(response);
  })
  
  }

  async function sendCircuit() {
    const response = await axios.post('http://localhost:8000/simulate',
        {circuit_matrix: circuit})
  .then(function(response: any){
    console.log(response);
    setStates(JSON.stringify(response.data.state_list));
  })}

  return (
    <div className="Circuitboard">
      <section className="circuit" ref={setNodeRef} style={style}>
          {qubitLines}
      </section>
      <button onClick={addQubit}>+</button>
      <button onClick={removeQubit}>-</button>
      <button onClick={ping}>ping</button>
      <button onClick={sendCircuit}>send example circuit</button>
      <section className="states"><h1 style={{ color: 'white' }}>{states}</h1></section>
    </div>
  );
}

function App() {
  const [parentH, setParentH] = useState(null);
  const [parentX, setParentX] = useState(null);
  const [parentY, setParentY] = useState(null);
  const [parentZ, setParentZ] = useState(null);
  const [gridSize, setGridSize] = React.useState(60);
  const snapToGrid = useMemo(() => createSnapModifier(gridSize), [gridSize]);

  return (
    <div className="App">
      <DndContext onDragEnd={handleDragEnd}>
        <Toolbar />
        <Circuitboard />
      </DndContext>
    </div>
  );

  function handleDragEnd(event:any) {
    // TODO limit number of draggables in droppable to 1.
    // probably by creating an isEmpty constant
    const {active, over} = event;
    if (active.id == 'X'){
      setParentX(over ? over.id : null);
    } else if(active.id == 'Y'){
      setParentY(over ? over.id : null);
    } else if(active.id == 'Z'){
      setParentZ(over ? over.id : null);
    } else if(active.id == 'H'){
      setParentH(over ? over.id : null);
    }
  }
}

export default App;

Here's the code for the gate component

import React from 'react';
import {useDraggable} from '@dnd-kit/core';
import {CSS} from '@dnd-kit/utilities';

export function Gate(props:any) {
    const {attributes, listeners, setNodeRef, transform} = useDraggable({
        id: props.name,
        data: {
          type: 'gate',
        },
      });
      const style = {
        transform: CSS.Translate.toString(transform),
        width: 60,
        height: 60
      };
      
      return (
        <button ref={setNodeRef} style={style} {...listeners} {...attributes}>
          <h1>{props.name}</h1>
        </button>
      );
}

All examples and documentation is either too simple or does not explain what I'm looking for

0

There are 0 best solutions below