首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >将数组设置为不起作用的状态

将数组设置为不起作用的状态
EN

Stack Overflow用户
提问于 2022-06-23 19:34:38
回答 1查看 44关注 0票数 0

在这个组件中,我在画布中的图像上绘制文本。我想跟踪所有的文本并存储它们的一些属性,但是当我将它们保存在一个状态中时,它们不会在UI中更新,而是在dev工具中更新。但是,当数组长度超过一个时,它只更新UI上的一个项,而只更新一个项。如果我的状态数组是1,2。在UI中,它只显示1。但是在react开发工具中,它是可以的。但是,如果我将文本存储在一个全局数组中,它就能正常工作。

组件

代码语言:javascript
运行
AI代码解释
复制
import { useRef, useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import "./styles/Generator.css";
//Why this one Work but not state
let textArr = [];
let startX, startY;
export default function Generator() {
  //const [textArr,setTextArr]=useState([]);
  const [text, setText] = useState("");
  const [isClear, setIsClear] = useState(false);
  const [image, setImage] = useState("");
  const [offsets, setOffsets] = useState({
    selectedText: -1,
    offsetX: 0,
    offsetY: 0,
  });
  const { state } = useLocation();
  const { item } = state;
  const canvasRef = useRef(null);
  let contextRef = useRef(null);

  useEffect(() => {
    const canvas = canvasRef.current;
    setOffsets({
      ...offsets,

      offsetX: canvasRef.current.offsetLeft,
      offsetY: canvasRef.current.offsetTop,
    });
    const context = canvas.getContext("2d");
    contextRef.current = context;
    //Our first draw
    let asp = item.width / item.height;
    canvas.width = 400;
    canvas.height = 400 / asp;
    const meme = new Image();
    meme.setAttribute("crossOrigin", "anonymous");
    meme.src = item.url;
    meme.onload = () => {
      context.drawImage(meme, 0, 0, canvas.width, canvas.height);
      setImage(meme);
    };
  }, [isClear]);
  const addText = () => {
    if (text.length < 1) return;
    var y = textArr.length * 20 + 20;
    // get the text from the input element

    var t = {
      text: text,
      x: 50,
      y: y + 70,
    };

    // calc the size of this text for hit-testing purposes
    contextRef.current.font = "20px arial";
    t.width = contextRef.current.measureText(t.text).width;
    t.height = 20;
    //setState([...textArr,t])
    textArr.push(t);
    draw();

    setText("");
  };

  const handleMouseDown = (e) => {
    e.preventDefault();
    startX = parseInt(e.clientX - offsets.offsetX);
    startY = parseInt(e.clientY - offsets.offsetY);
    textArr.map((i, index) => {
      if (textHittest(startX, startY, index)) {
        return setOffsets({ ...offsets, selectedText: index });
      }
    });
  };
  const handleMouseMove = (e) => {
    if (offsets.selectedText < 0) {
      return;
    }
    e.preventDefault();
    let mouseX = parseInt(e.pageX - offsets.offsetX);
    let mouseY = parseInt(e.pageY - offsets.offsetY);
    var text = textArr[offsets.selectedText];
    text.y += dy;
    startX = mouseX;
    draw();
  };
  const handleMouseUp = (e) => {
    e.preventDefault();
    setOffsets({ ...offsets, selectedText: -1 });
  };
  function textHittest(x, y, textIndex) {
    var text = textArr[textIndex];
    const isTrue =
      x >= text.x &&
      x <= text.x + text.width &&
      y >= text.y - text.height &&
      y <= text.y;
    return isTrue;
  }

  function handleMouseOut(e) {
    e.preventDefault();
    setOffsets({ ...offsets, selectedText: -1 });
  }
  const draw = () => {
    contextRef.current.drawImage(
      image,
      0,
      0,
      canvasRef.current.width,
      canvasRef.current.height
    );

    textArr.length > 0 &&
      textArr.map((i) => {
        contextRef.current.fillText(i.text, i.x, i.y);
        return;
      });
  };
  const download = () => {
    let img = canvasRef.current
      .toDataURL("image/png", 1.0)
      .replace("image/png", "image/octet-stream");
    var link = document.createElement("a");
    link.download = "my-image.png";
    link.href = img;
    link.click();
  };
  return (
    <div className="generator">
      <div className="generator__container">
        <div className="generator__header">
          <h1 className="home__title">Meme-Generator</h1>
          <a href="/" className="home__link-top">
            back
          </a>
        </div>
        <div className="generator__content">
          <div className="generator__left">
            <canvas
              onMouseDown={handleMouseDown}
              onMouseMove={handleMouseMove}
              onMouseUp={handleMouseUp}
              onMouseOut={handleMouseOut}
              ref={canvasRef}
              className="canvas"
            />
            <div className="generator__btn-container">
              <button onClick={download} className="generator__btn">
                Download
              </button>
            </div>
          </div>
          <div className="generator__right">
            <h3 className="generator__sub-title">Add Text to Meme</h3>
            <label className="generator__label" htmlFor="text1">
              Enter Text
            </label>
            <input
              value={text}
              className="generator__input"
              type="text"
              placeholder="Enter text.."
              onChange={(e) => setText(e.target.value)}
            />
            <button
              onClick={addText}
              className="generator__btn generator__btn--text"
            >
              Add Text
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

State

代码语言:javascript
运行
AI代码解释
复制
//setting array like this work
let textArr = [];
let startX, startY;
export default function Generator() {
  //setting state like this doesn't work
  //const [textArr,setTextArr]=useState([]); 
  return (....)
}

添加文本函数

代码语言:javascript
运行
AI代码解释
复制
const addText = () => {
  if (text.length < 1) return;
  var y = textArr.length * 20 + 20;

  var t = {
    text: text,
    x: 50,
    y: y + 70,
  };
  contextRef.current.font = "20px arial";
  t.width = contextRef.current.measureText(t.text).width;
  t.height = 20;
  //state updating like this don't effect on UI but it update on devtools
  //setState([...textArr,t])
  //This like work just fine
  textArr.push(t);
  draw();

  setText("");
};
EN

回答 1

Stack Overflow用户

发布于 2022-06-23 19:45:56

状态更新是异步的,但是在设置了新状态(状态尚未更新时),就调用了“绘制”函数。

如果您希望每次更新textArr时绘图函数都能工作,则需要使用效果钩子。应该像这样工作:

代码语言:javascript
运行
AI代码解释
复制
useEffect(() => {
  draw();
}, [textArr]);

如果绘图函数依赖于其他值,那么也应该将它们包含到依赖项数组中(就在textArr之后)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72738718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文