Nano Hash - криптовалюты, майнинг, программирование

React-dnd drag update db в mongo с метеором для сохранения порядка при обновлении страницы

Я использую перетаскивание response-dnd и имею отсортированный список, который отображается, он работает отчасти, я могу перетаскивать и отпускать, и при обновлении кажется, что все осталось в правильном положении, но элемент перемещается на одну строку, чем то, куда я перетащил Это.

Основная проблема заключается в том, что когда я перетаскиваю элемент и бросаю его, состояние карточек в moveCardDb немного отличается, чем за пределами функции, почему в этот момент я не могу понять.

Вот минимальная настройка того, что у меня есть https://codesandbox.io/s/gifted-goodall-qu43p?file=/src/Container.jsx

Если вы посмотрите журнал консоли функции moveCardDb, вы увидите, что переменная карты stae немного не в порядке.

Заранее спасибо

У меня есть следующий код для перетаскивания

Функция отображения и обновление позиции

  const [cards, setCards] = useState([]);
  let stateReplace = useMemo(() => {
    if (!isLoading && formBuilder?.inputs?.length) {
      return formBuilder.inputs;
    }
    return [];
  }, [isLoading]);

  useEffect(() => {
    setCards(stateReplace);
  }, [setCards, stateReplace]);

  // console.log(cards);

  const moveCard = useCallback(
    (dragIndex, hoverIndex) => {
      console.log(dragIndex);
      console.log(hoverIndex);
      const dragCard = cards[dragIndex];
      setCards(
        update(cards, {
          $splice: [
            [dragIndex, 1],
            [hoverIndex, 0, dragCard],
          ],
        })
      );
    },
    [cards]
  );

  const moveCardDb = useCallback(() => {
    //console.log(cards);

    Meteor.call("formLeadBuilderDrag.update", cards, params._id, function (
      error,
      result
    ) {
      console.log(result);
      console.log(error);
    });
  }, [cards]);

  const renderCard = (card, index) => {
    return (
      <>
        {isLoading ? (
          <div className="loading">loading...</div>
        ) : (
          <>
            <Card
              key={card.dragPositionId}
              index={index}
              id={card.dragPositionId}
              input={card.inputType}
              moveCard={moveCard}
              moveCardDb={moveCardDb}
            />
          </>
        )}
      </>
    );
  };
  return (
    <>
      {isLoading ? (
        <div className="loading">loading...</div>
      ) : (
        <form>
          <div style={style}>{cards.map((card, i) => renderCard(card, i))}</div>
          <input type="submit" />
        </form>
      )}
    </>
  );

Карта предоставлена

import React, { useRef } from "react";
import { useDrag, useDrop } from "react-dnd";
import { ItemTypes } from "./ItemTypes";
const style = {
  border: "1px dashed gray",
  padding: "0.5rem 1rem",
  marginBottom: ".5rem",
  backgroundColor: "white",
  cursor: "move",
};
export const Card = ({ id, input, index, moveCard, moveCardDb }) => {
  const ref = useRef(null);
  const [, drop] = useDrop({
    accept: ItemTypes.CARD,
    hover(item, monitor) {
      if (!ref.current) {
        return;
      }
      const dragIndex = item.index;
      const hoverIndex = index;
      // Don't replace items with themselves
      if (dragIndex === hoverIndex) {
        return;
      }
      // Determine rectangle on screen
      const hoverBoundingRect = ref.current?.getBoundingClientRect();
      // Get vertical middle
      const hoverMiddleY =
        (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
      // Determine mouse position
      const clientOffset = monitor.getClientOffset();
      // Get pixels to the top
      const hoverClientY = clientOffset.y - hoverBoundingRect.top;
      // Only perform the move when the mouse has crossed half of the items height
      // When dragging downwards, only move when the cursor is below 50%
      // When dragging upwards, only move when the cursor is above 50%
      // Dragging downwards
      if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
        return;
      }
      // Dragging upwards
      if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
        return;
      }
      // Time to actually perform the action
      moveCard(dragIndex, hoverIndex);
      moveCardDb();
      // Note: we're mutating the monitor item here!
      // Generally it's better to avoid mutations,
      // but it's good here for the sake of performance
      // to avoid expensive index searches.
      item.index = hoverIndex;
    },
  });
  const [{ isDragging }, drag] = useDrag({
    item: { type: ItemTypes.CARD, id, index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });
  const opacity = isDragging ? 0 : 1;
  drag(drop(ref));
  return (
    <div ref={ref} style={{ ...style, opacity }}>
      <p>{input}</p>
      <input
        name={input + id}
        defaultValue="test"
        // ref={register}
      />
      {/* <button type="button" onClick={onEditToggle}>
        <BiEditAlt size={25} />
      </button> */}
      {/* <button onClick={() => deleteLead(leads)}>&times;</button> */}
    </div>
  );
};

Мой объект с самого начала

{
  "_id": "showRoomId",
  "type": "Show Room Lead",
  "createdAt": "2020-11-14",
  "userId": "83nfd298dn382",
  "inputs": [
    {
      "inputType": "shortText",
      "dragPositionId": "1",
      "label": "First Name:"
    },
    {
      "inputType": "phoneNumber",
      "dragPositionId": "2",
      "label": "Cell Phone Number"
    },
    {
      "inputType": "email",
      "dragPositionId": "3",
      "label": "Work Email"
    },
    {
      "inputType": "Address",
      "dragPositionId": "4",
      "label": "Home Address"
    },
    {
      "inputType": "multipleChoice",
      "dragPositionId": "5",
      "label": "Preferred Method of Contact",
      "options": [
        {
          "dragPositionId": "1",
          "label": "Email"
        },
        {
          "dragPosition": "2",
          "label": "Cell Phone"
        }
      ]
    },
    {
      "inputType": "dropDown",
      "dragPositionId": "6",
      "label": "How did you find us?",
      "options": [
        {
          "dragPositionId": "1",
          "label": "Google"
        },
        {
          "dragPosition": "2",
          "label": "Referral"
        }
      ]
    }
  ]
}

Ответы:


1

Вы предоставили кучу кода, и это хорошо, но я не понимаю, в чем проблема, и что вы пытались исправить. Хранятся ли вещи в БД так, как вы ожидаете, или это проблема рендеринга?

14.11.2020
  • Вещи хранятся в БД в виде нового массива, отсортированного в том порядке, в котором они были выведены, при покупке переменной состояния карты. Однако он немного не по порядку, потому что правильное состояние отображается после запуска moveCardDb, поэтому он видит свою предыдущую позицию на 1 и сохраняет ее там при обновлении. Я думаю, что могу получить рабочий пример без db, но это если он консольет неправильный порядок внутри функции moveCardDb. Я сделаю это сейчас 15.11.2020
  • Извините, это должен был быть комментарий, а не ответ. То есть вы видите какое-то состояние гонки, т.е. сохранение запускается в неправильное время, до того, как порядок был установлен правильно? 15.11.2020
  • Я думаю, что да, я поставил песочницу кода, и если вы посмотрите на консоль, вы увидите, где она вышла из строя по одному, и в этом момент я сохраняю ее, делаю свой db 15.11.2020

  • 2

    Я закончил тем, что наложил время на функцию в функции monitor.didDrop. Мне это кажется немного взломанным, поэтому, если кто-то может предложить лучшее решение, дайте мне знать. Я также решил сначала сохранить в localstorage, а затем отправить в базу данных при отправке формы.

     const [{ isDragging, didDrop }, drag] = useDrag({
        item: { type: ItemTypes.CARD, id, index },
        collect: (monitor) => ({
          isDragging: monitor.isDragging(),
          didDrop: monitor.didDrop(),
        }),
      });
      const opacity = isDragging ? 0 : 1;
    
      function droppy(dropped) {
        var delayInMilliseconds = 1000; //1 second
    
        setTimeout(function () {
          dropped();
        }, delayInMilliseconds);
      }
    
      if (didDrop) {
        droppy(moveCardDb);
      }
    
    15.11.2020
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..