You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中多条Polyline无法显示的问题求助

问题修复方案

核心问题与修复步骤

  1. 违反React状态不可变原则:直接修改原状态数组,导致React无法检测到状态变化
  2. forEach无法生成React元素:forEach无返回值,无法渲染元素列表,需改用map
  3. SVG属性错误:polyline的属性名应为points而非point;SVG的hanging是无效属性,需改为height
  4. 初始点缺失:未记录鼠标按下时的初始坐标,导致每条线的第一个点丢失
  5. 状态更新闭包问题:直接依赖外部状态变量更新,需用函数式更新确保获取最新状态

修复后的完整代码

import { useState, useEffect } from "react";

export default function DrawKanji({ advance, randomSet }) {
  const [stroke, setStroke] = useState([]);
  const [kanji, setKanji] = useState([]);
  const [draw, setDraw] = useState(false);

  useEffect(() => {
    console.log("kanji updated:", kanji);
    console.log("stroke updated:", stroke);
  }, [kanji, stroke]);

  const clearPractice = () => {
    setKanji([]);
  };

  const handleMouseDown = (event) => {
    const { clientX, clientY } = event;
    const offset = document.getElementById("svg").getBoundingClientRect();
    setDraw(true);
    // 记录鼠标按下时的初始点
    setStroke([{ x: clientX - offset.left, y: clientY - offset.top }]);
  };

  const handleMouseMove = (event) => {
    const { clientX, clientY } = event;
    const offset = document.getElementById("svg").getBoundingClientRect();
    if (draw) {
      // 函数式更新避免闭包导致的状态滞后
      setStroke(prevStroke => [
        ...prevStroke,
        { x: clientX - offset.left, y: clientY - offset.top },
      ]);
    }
  };

  const handleMouseUp = () => {
    // 创建新数组,遵循状态不可变原则
    setKanji(prevKanji => [...prevKanji, stroke]);
    setStroke([]);
    setDraw(false);
  };

  const drawLine = (
    <>
      {kanji.map((line, index) => (
        <polyline
          key={index}
          points={line.map((point) => `${point.x},${point.y}`).join(" ")}
          stroke="black"
          strokeWidth="2"
          fill="none"
        />
      ))}
    </>
  );

  return (
    <>
      <p>{stroke.length > 1 ? JSON.stringify(stroke[1]) : ""}</p>
      <button onClick={advance} name="previous" disabled={randomSet}>
        Previous
      </button>
      <svg
        id="svg"
        onMouseDown={handleMouseDown}
        onMouseMove={handleMouseMove}
        onMouseUp={handleMouseUp}
        width="109px"
        height="100px"
        style={{ border: "1px solid black" }}
      >
        {drawLine}
      </svg>
      <button onClick={advance} name="next">
        Next
      </button>
      <p>
        <button onClick={clearPractice}>Clear</button>
      </p>
    </>
  );
}

关键修复说明

  • 状态不可变处理:通过setKanji(prevKanji => [...prevKanji, stroke])创建新数组,让React能检测到状态变化并触发重渲染
  • map替代forEach:map返回元素数组供React渲染,同时添加key属性满足列表渲染要求
  • SVG属性修正:修复polyline的属性名,补充stroke、strokeWidth等属性确保线条可见,修正SVG尺寸属性
  • 初始点记录:在handleMouseDown中立即记录起点,保证每条线的完整性
  • 函数式状态更新:避免闭包导致的状态滞后问题,确保每次更新都基于最新的状态值

内容的提问来源于stack exchange,提问作者LeoSeattle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 23:35:31