React 数组在修改时不呈现

问题描述 投票:0回答:2

你好,我有一个组件,它接受一个字符串数组并将它们组合起来,然后通过将每个字符包装在 span 标签中并将不透明度从 0 切换到 1 来呈现一个输入动画。

我确实切换了 displayedText[0] 和 displayedText[1],反之亦然 displayedText[0] 正在渲染,而 displayedText[1] 已发送。

代码如下:

"use client";
import Link from "next/link";
import { useEffect, useState } from "react";
import { useInterval } from "src/hooks/setInterval";

type Props = { text: string[]; aniLength: number };

export default function TypeIn({ text, aniLength }: Props) {
  const fullText = text.join("");
  const [numPrintedLetter, setNumPrintedLetter] = useState<number>(0);
  const [numPrintedStrings, setNumPrintedStrings] = useState<number>(0);
  const [delay, setDelay] = useState<number | null>(
    aniLength / fullText.length
  );

  const [displayedText, setDisplayedText] = useState<JSX.Element[][]>(() =>
    text.map((stringArr) =>
      stringArr.split("").map((letter, i) => (
        <span key={i} style={{ opacity: "0" }}>
          {letter}
        </span>
      ))
    )
  );

  useEffect(() => {
    if (text.length <= 0) throw Error("CAN NOT TYPE IN NOTHING");
  }, [text]);

  useInterval(() => {
    if (numPrintedLetter < text[numPrintedStrings].length) {
      // Here is the place where code per character is executed
      setDisplayedText((prevText) => {
        let curNewElement = (
          <span
            key={prevText[numPrintedStrings][numPrintedLetter].key}
            style={{ opacity: "1.0" }}
          >
            {prevText[numPrintedStrings][numPrintedLetter].props.children}
          </span>
        );
        prevText[numPrintedStrings][numPrintedLetter] = curNewElement;
        return prevText;
      });

      setNumPrintedLetter(numPrintedLetter + 1);
    } else {
      // subtract one to compensate for 0 index
      if (numPrintedStrings >= text.length - 1) {
        setDelay(null);
      } else {
        setNumPrintedLetter(0);
        setNumPrintedStrings(numPrintedStrings + 1);
      }
    }
  }, delay);

  useEffect(() => {
    console.log("displayedText", displayedText);
  }, [displayedText]);

  return (
    <>
      <h1 className={`text-stroke-2 pt-[max(76px,32vh)]`}>
        {displayedText[0]}

        <Link
          href="/contact"
          className="text-transparent dark:text-stroke-white text-stroke-black text-stroke-2
dark:hover:text-white hover:text-black
transition-all ease-in-out duration-300"
        >
          {displayedText[1]}
        </Link>
      </h1>
    </>
  );
}

这里是回购协议:https://github.com/laycookie/Portfolio/blob/Development/src/components/TypeIn.tsx

javascript reactjs typescript next
2个回答
1
投票

你在这里改变你的状态。

prevText[numPrintedStrings][numPrintedLetter] = curNewElement;

首先尝试制作克隆。

// Here is the place where code per character is executed
setDisplayedText((prevText) => {
  const newText = [...prevText];

  let curNewElement = (
    <span
      key={newText[numPrintedStrings][numPrintedLetter].key}
      style={{ opacity: "1.0" }}
    >
      {newText[numPrintedStrings][numPrintedLetter].props.children}
    </span>
  );

  newText[numPrintedStrings][numPrintedLetter] = curNewElement;

  return newText;
});

0
投票

我仍然不知道为什么

{displayedText[0]}
没有更新,但我找到了
displayedText[1]
更新的原因。事实证明,将 {displayedText[num]} 包装在 Link 或 span 等其他标签中为我解决了这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.