Я пытаюсь создать компонент реагирования, который позволяет пользователю перетаскивать случайно сгенерированные слова из нескольких категорий, чтобы создать короткую фразу. Каждый из перетаскиваемых элементов слова имеет одну из этих категорий в качестве своего типа. Я хочу, чтобы цель перетаскивания перетаскивалась так, чтобы она принимала только одно из каждой категории слов, и я столкнулся с очень странным поведением из библиотеки для этой, казалось бы, простой операции.
Сначала я попытался создать экземпляр массиваfreeCategories, который включает в себя все категории слов, затем перебирает переменную состояния currentPhrase (также массив) и удаляет каждую категорию, которая используется в настоящее время. реквизит, а затем использовать его в качестве значения для «принять» в useDrop. Это просто пропускало что-либо, независимо от того, что было в массиве freeCategories.
Мое второе решение состояло в том, чтобы выполнить эту логику над объектом перетаскивания. Если категория слова все еще доступна, она будет удалена из freeCategories, а ее тип будет «word-usable» или «word-block», если это не так. Если для параметра перенаправления цели назначения установлено значение «word-usable», оно все равно будет принимать что-либо, даже если его тип возвращался как «заблокированный словом».
Наконец, я попытался добавить свойство canDrop для useDrop. Это проверило массив freeCategories (переданный в реквизитах) по типу элемента (теперь возвращается к категории слова). Это привело к тому, что цель отбрасывания блокирует все, а canDrop возвращает false, даже если тип слова был в массиве свободных категорий. Когда я попытался переключить монитор с !! monitor.canDrop на! Monitor.canDrop, теперь он выглядит так, как будто он примет любое слово, но при отбрасывании он не запускает функцию сброса.
Функция, которая создаетjsx фразы:
function currentPhraseDisp() {
let freeCategories = ["Form", "Element", "Verb"];
currentPhrase.forEach(word => freeCategories.splice(freeCategories.indexOf(word.category), 1));
let startSpace = currentSpell.length < 3 ? <WordSpace start={true} accepts={freeCategories} addWordToCurrentPhrase={addWordToCurrentPhrase} /> : <></>;
return (
<>
{startSpace}
{currentPhrase.map((w, i) => {
return (
<div key={i} className="current-phrase-word">
<div>{w['word']}</div>
<button>-</button>
</div>
)
})}
</>
)
}
Слова появляются как объекты в формате {слово: 'слово', категория: 'категория слова'}
Логика перетаскивания:
const [{ isDragging }, drag] = useDrag({
/*Used in the second solution*/ item: { type: 'word-usable', id: props.word },
item: { type: props.word.category, id: props.word},
collect: monitor => ({
isDragging: !!monitor.isDragging()
})
})
Логика удаления:
const [{ isOver, canDrop }, drop] = useDrop({
accept: props.accepts,
/*Used in solution 3
canDrop: (item) => {
props.accepts.includes(item.type);
},
*/
drop: (item) => {
props.addWordToCurrentPhrase(item.id, props.start);
},
collect: monitor => ({
isOver: !!monitor.isOver(),
canDrop: !!monitor.canDrop()
})
})
Мне бы хотелось, чтобы эти компоненты позволили пользователю перетаскивать только один из любого данного типа слова в currentPhrase. До сих пор мои результаты заключались в том, что цель отбрасывания принимает все слова или нет слов. Если кто-нибудь может помочь мне понять, что происходит с реакцией, я был бы признателен, потому что похоже, что он не позволит принимать какие-либо изменения или типы элементов при повторном отображении.