更新通过 props 传输的数组

Update array that is transmitted through props

标题可能有点含糊,但我会更好地解释:)

所以我有这个组件DraggableGameSlots.tsx

import React, { useState } from "react";
import DraggableGameSlot from "./DraggableGameSlot";

type DraggableGameSlotsProps = {
    numberOfAnswers: number,
    slotFor: string
}

function DraggableGameSlots(props: DraggableGameSlotsProps) {
    const [answers, setAnswers] = useState<string[]>(Array<string>(props.numberOfAnswers).fill("Drop here"));

    return (
        <div className="draggable-game-slots">
            {
                answers.map((val, index) => (
                    <DraggableGameSlot
                        className={props.slotFor === "text" ? "draggable-game-slot-for-text" : "draggable-game-slot-for-image"}
                        key={index}
                        answers={answers}
                        setAnswers={setAnswers}
                    />
                ))
            }
        </div>
    );
}

export default DraggableGameSlots;

和DraggableGameSlot.tsx

import { useEffect, useRef } from 'react';
import { useDrop } from 'react-dnd';
import './css/DraggableGameSlot.css';

type DraggableGameSlotProps = {
    className: string,
    answers: any,
    setAnswers: any
}

function DraggableGameSlot(props: DraggableGameSlotProps) {          
    const [{isOver}, drop] = useDrop(() => ({
        accept: "image",
        drop(item: {id: string}) {
            props.setAnswers([...props.answers, item.id]);
            console.log(props.answers);
        },
        collect: (monitor) => ({
            isOver: !!monitor.isOver(),
        })
    }))

    useEffect(() =>
        console.log(props.answers)
    );
      
    return (
        <div className={`draggable-game-slot ${props.className}`} ref={drop}>
            <span>Drop here</span>
        </div>
    )
}

export default DraggableGameSlot;

逻辑如下:

我有一系列答案,我想使用 react-dnd 添加新答案。最初的答案是“拖放到这里”(因为它们没有定义,所以只会出现带有这段文字的槽 - 我稍后会实现这个逻辑)。

所以我有一个包含所有答案的数组。我渲染它们,一切都很好。

然后我有一个来自 react-dnd 的 useDrop 挂钩 - 它用于定义可拖动项目的放置目标。这也不是帖子的重点:)

我观察到使用 DraggableGameSlot 中的两个 console.logs,对于 numberOfAnswers = 4,当我放下答案并调用 drop 时,我的数组将是长度 = 4(初始)或长度 = 5。

我预计每次删除答案并调用 props.setAnswers 时,都会在数组末尾添加一个新答案。嗯,这样不行,其实每次都改第5项

例如

Drop here Drop here Drop here Drop here

I drag answer1:

Expectation: Drop here Drop here Drop here Drop here answer1
Behavior: Drop here Drop here Drop here Drop here answer1
OK

I drag answer2:
Expectation: Drop here Drop here Drop here Drop here answer1 answer2
Behavior: Drop here Drop here Drop here Drop here answer2

NOT OK

我怀疑这是因为 props.answers 没有更新。通过道具而不是参考传递它时,我可能会得到它的值的副本,所以当我调用 setAnswers 时,answers 数组仅在 DraggableGameSlots 中更新并且 props.answers 保持不变。

好吧,我不想那样。

为什么会这样,我怎样才能让它按我想要的方式工作? :)

当仔细观察useDrop时,它使用记忆(依赖数组)和空数组作为默认值。您应该添加可以更改的依赖项数组(answerssetAnswers 等)作为 useDrop.

的第二个参数