【问题标题】:React component not passing value to correct component反应组件没有将值传递给正确的组件
【发布时间】:2023-01-31 00:26:53
【问题描述】:

我有一个简单的 React 应用程序,它使用 react-dnd 构建可拖动方块的网格,这些方块具有初始颜色和文本值以及两个组件来更改颜色和更改文本。

颜色变化(通过 ColorPicker2,使用 react-color 库)工作正常。文本更改(使用来自@carbon/react 的 TextInput)没有按预期工作。

我以为我对这两个组件应用了相同的逻辑,但是当颜色选择器更新颜色并在移动正方形时保留该颜色时,文本似乎呈现在 TextInput 内部而不是正方形本身,我无法理解出逻辑差异。

代码沙箱在这里:https://codesandbox.io/s/wild-waterfall-z8s1de?file=/src/App.js

这是当前代码:

取色器2.js

import "./styles.css";
import React from "react";
import { BlockPicker } from "react-color";

const presetColors = ["#9E9E9E", "#4CAF50", "#FFEB3B", "#F44336", "#2196F3"];

const ColorPicker2 = (props) => {
  const handleChangeComplete = (color) => {
    if (props.updateColor) {
      props.updateColor(color.hex);
    }
  };

  return (
    <div className="palette">
      <BlockPicker
        className="palette"
        colors={presetColors}
        onChangeComplete={handleChangeComplete}
        presetColors={Object.values(presetColors)}
        color={props.currentColor}
      />
    </div>
  );
};

export default ColorPicker2;

应用程序.js

import "./styles.css";
import React, { useState } from "react";
import { DndProvider, useDrag, useDrop } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import edit from "./edit.svg";
import palette from "./palette.svg";
import ColorPicker2 from "./ColorPicker2";
import { TextInput } from "@carbon/react";

const DndWrapper = (props) => {
  return <DndProvider backend={HTML5Backend}>{props.children}</DndProvider>;
};

const DraggableSquare = ({ index, text, color, moveSquare }) => {
  const [{ isDragging }, drag] = useDrag({
    type: "square",
    item: { index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging()
    })
  });

  const [isHovered, setIsHovered] = useState(false);
  const [, drop2] = useDrop({
    accept: "square",
    drop: (item, monitor) => {
      const didDrop = monitor.didDrop();
      if (!didDrop) {
        moveSquare(item.index, index);
      }
    },
    hover: (item, monitor) => {
      setIsHovered(monitor.isOver());
    },
    collect: (monitor) => {
      setIsHovered(monitor.isOver());
    }
  });

  const [isPaletteOpen, setIsPaletteOpen] = useState(false);
  const [isTextInputOpen, setIsTextInputOpen] = useState(false);
  const [newText, setNewText] = useState(text);

  const opacity = isDragging ? 0.5 : 1;

  return (
    <div className="square-div" ref={drop2}>
      <div
        className="grey-square"
        ref={drag}
        style={{
          opacity,
          backgroundColor: color,
          width: "200px",
          height: "200px",
          textAlign: "center",
          paddingTop: "30px",
          position: "relative",
          border: isHovered ? "3px solid blue" : "none",
          borderRadius: "5px",
        }}
        onMouseOver={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
      >
        <img
          src={edit}
          onClick={() => {
            setIsTextInputOpen(!isTextInputOpen);
            if (!isTextInputOpen) {
              moveSquare(index, newText, color, undefined);
            }
          }}
          style={{
            width: "15px",
            height: "15px",
            position: "absolute",
            right: "5px",
            top: "5px"
          }}
          alt="edit icon"
        />

        {isTextInputOpen && (
          <TextInput
          id="newtext"
          labelText=""  
            value={newText}
            onChange={(e) => setNewText(e.target.value)}
          />
        )}
        <img
          src={palette}
          onClick={() => setIsPaletteOpen(!isPaletteOpen)}
          style={{
            width: "15px",
            height: "15px",
            position: "absolute",
            right: "25px",
            top: "5px"
          }}
          alt="palette icon"
        />

        {isPaletteOpen && (
          <ColorPicker2
          className="palette"
            currentColor={color}
            updateColor={(newColor) =>
              moveSquare(index, index, newText, newColor)
            }
          />
        )}
      </div>
    </div>
  );
};
const Grid = () => {
  const [grid, setGrid] = useState([
    { text: "1", color: "grey" },
    { text: "2", color: "grey" },
    { text: "3", color: "grey" },
    { text: "4", color: "grey" },
    { text: "5", color: "grey" },
    { text: "6", color: "grey" },
    { text: "7", color: "grey" },
    { text: "8", color: "grey" },
    { text: "9", color: "grey" },
    { text: "10", color: "grey" },
    { text: "11", color: "grey" },
    { text: "12", color: "grey" },
    { text: "13", color: "grey" },
    { text: "14", color: "grey" },
    { text: "15", color: "grey" }
  ]);

  const moveSquare = (fromIndex, toIndex, newText, newColor) => {
    setGrid((grid) => {
      const newGrid = [...grid];
      const item = newGrid[fromIndex];
      newGrid.splice(fromIndex, 1);
      newGrid.splice(toIndex, 0, {
        text: newText || item.text,
        color: newColor || item.color
      });
      return newGrid;
    });
  };

  return (
    <>
      <DndWrapper>
        <div
          className="grid"
          style={{
            display: "grid",
            gridTemplateColumns: "repeat(5, 190px)",
            gridGap: "15px",
            gridColumnGap: "20px",
            gridRowGap: "10px",
            position: "absolute"
          }}
        >
          {grid.map((square, index) => (
            <DraggableSquare
              key={index}
              index={index}
              text={square.text}
              color={square.color}
              moveSquare={moveSquare}
              //grid={grid}
              //setGrid={setGrid}
            />
          ))}
        </div>
      </DndWrapper>
    </>
  );
};

export default Grid;

任何新鲜的想法都会有所帮助。

【问题讨论】:

    标签: reactjs react-hooks react-dnd carbon-design-system react-color


    【解决方案1】:

    我认为这只是在映射时使用索引作为键的一个简单问题。调整你的代码笔,让一个唯一的键为我修复它,但输入文本没有保存在任何地方,所以当按预期移动时返回到默认文本={square.text}。

    对象中的唯一 ID:

      const [grid, setGrid] = useState([
        { text: "1", color: "grey", id: crypto.randomUUID() },
        { text: "2", color: "grey", id: crypto.randomUUID() },
        { text: "3", color: "grey", id: crypto.randomUUID() },...])
    

    将键添加到映射对象:

     {grid.map((square, index) => (
                <DraggableSquare
                  key={square.id}
                  index={index}
                  text={square.text}
                  color={square.color}
                  moveSquare={moveSquare}
                  //grid={grid}
                  //setGrid={setGrid}
                />}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-21
      • 1970-01-01
      • 2019-01-02
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      相关资源
      最近更新 更多