我的博客写作输入在React中删除了最后一行。

huangapple go评论70阅读模式
英文:

my blog writing input is removing last line in react

问题

这是当前状态,我有4行代码和第5行在当前输入中。

这是我的React代码,我正在尝试让它像Medium一样工作,您可以单独编辑每一行。

英文:

我的博客写作输入在React中删除了最后一行。

this is the current state where I have 4 lines and 5th line in current input

and this is my react code


import { FC, useEffect, useState } from "react";

interface BlogWitterProps {}

const BlogWitter: FC<BlogWitterProps> = ({}) => {
  const [markdownContent, setMarkdownContent] = useState("");
  const [currentLine, setCurrentLine] = useState("");

  // on each new line, update the markdown content

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

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      setMarkdownContent((prev) => {
        return prev + currentLine + "\n";
      });
      setCurrentLine("");
    } else if (e.key === "Backspace" && currentLine === "") {
      e.preventDefault();
      setMarkdownContent((prev) => {
        const lines = prev.split("\n");
        const lastLine = lines.pop();
        console.log("lines", lines);

        setTimeout(() => {
          // If the last line is not empty, update the current line state
          if (lastLine !== "") {
            setCurrentLine(lastLine + "\n");
          } else {
            setCurrentLine("");
          }
        }, 0);

        return lines.join("\n");
      });
    }
  };

  return (
    <div className="">
      <div>
        {markdownContent.split("\n").map((line, index) => {
          return (
            <div key={index}>
              {line}
              <br />
            </div>
          );
        })}
      </div>
      <input
        value={currentLine}
        onChange={(e) => {
          setCurrentLine(e.target.value);
        }}
        className="w-full resize-none outline-none text-2xl bg-transparent border border-black"
        onKeyDown={handleKeyDown}
      />
    </div>
  );
};

export default BlogWitter;

so if I press backspace and it takes me to last line to edit then press anter again without changing anything it is remove the last line's new line and gives me this

我的博客写作输入在React中删除了最后一行。

I am trying to get it to work as in medieum where you can edit each line seperatly

答案1

得分: 1

以下是您要翻译的内容:

"事件序列在字符代码打印到控制台的情况下更容易理解markdownContent

下面,我重新粘贴了代码,并添加了一些测试代码(第16-21行),以将markdownContent显示为一系列由管道(|)字符分隔的ASCII字符代码。

关键序列和markdownContent字符代码

步骤 关键序列 输入字段 字符代码
1 A + Enter A 65 | 10
2 B + Enter B 65 | 10 | 66 | 10
3 C + Enter C 65 | 10 | 66 | 10 | 67 | 10
4 退格 65 | 10 | 66 | 10 | 67
5 退格 C 65 | 10 | 66
6 输入 65 | 10 | 66 | 67 | 10 | 10

通过代码步进

步骤4中,按下退格键执行第33行。这会将步骤3中的字符代码拆分为chr(10)(换行符)。第34行弹出最后一个字符(换行符),第42行将其丢弃,因为输入文本字段为空(调用了setCurrentLine(""))。

步骤5中,再次按下退格键(因为在步骤4之后输入字段未移动)。再次执行第33行,将步骤4中的字符拆分为换行符,弹出第34行的chr(67)(字母C),丢弃C。在按下退格键之前,输入表单字段为空,导致调用setCurrentLine("")C被从markdownContent中丢弃,但被重新添加到输入文本字段中。

步骤6中,按下Enter键会导致问题的描述。在这里,步骤5中的字符与currentLine连接:(C)+ Enter(刚刚按下的Enter键)。这就是字母BC被连接在一起的地方。原始的换行符将这两个字符分开,被第33行中的split()调用在步骤5中消耗。第27行添加了第二个换行符。这就是我们在步骤6中看到两个换行符的原因。

注意事项

在文本输入正确运行之前,需要考虑几种情况和边界情况。

代码

import * as React from "react";

const { useEffect, useState } = React;

interface BlogWitterProps {}

const BlogWitter: React.FunctionComponent<BlogWitterProps> = ({}) => {
  const [markdownContent, setMarkdownContent] = useState("");
  const [currentLine, setCurrentLine] = useState("");

  // 在每一行结束时,更新markdown内容

  useEffect(() => {
    console.log("markdownContent", markdownContent);
    console.log("currentLine", currentLine);
    let chars = [];
    for (let c of markdownContent) {
      chars.push(c.charCodeAt(0));
    }
    let codeString = chars.join('|');
    console.log('codes: ' + codeString);
  }, [currentLine, markdownContent]);

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      setMarkdownContent((prev) => {
        return prev + currentLine + "\n";
      });
      setCurrentLine("");
    } else if (e.key === "Backspace" && currentLine === "") {
      e.preventDefault();
      setMarkdownContent((prev) => {
        const lines = prev.split("\n");
        const lastLine = lines.pop();
        console.log("lines", lines);

        setTimeout(() => {
          // 如果最后一行不为空,更新当前行状态
          if (lastLine !== "") {
            setCurrentLine(lastLine + "\n");
          } else {
            setCurrentLine("");
          }
        }, 0);

        return lines.join("\n");
      });
    }
  };

  return (
    <div className="">
      <div>
        {markdownContent.split("\n").map((line, index) => {
          return (
            <div key={index}>{ line }</div>
          );
        })}
      </div>
      <input
        value={currentLine}
        size={80}
        onChange={(e) => {
          setCurrentLine(e.target.value);
        }}
        className="w-full resize-none outline-none text-2xl bg-transparent border border-black"
        onKeyDown={handleKeyDown}
      />
    </div>
  );
};

export default BlogWitter;

"

英文:

The sequence of events is easier to understand when the character codes for markdownContent are printed to the console.

Below, I've re-pasted the code, with some test code in place (LINES 16-21) to display markdownContent as a series of ASCII character codes separated by the pipe (|) character.

Key sequences and markdownContent char codes

step key sequence input field char codes
1 A + Enter A 65 | 10
2 B + Enter B 65 | 10 | 66 | 10
3 C + Enter C 65 | 10 | 66 | 10 | 67 | 10
4 Backspace 65 | 10 | 66 | 10 | 67
5 Backspace C 65 | 10 | 66
6 Enter 65 | 10 | 66 | 67 | 10 | 10

Stepping through the code

At step 4, pressing Backspace executes LINE 33. This splits the character codes in step 3 by chr(10) (linefeed). LINE 34 pops the last character (linefeed), and LINE 42 discards it since the input text field is blank (setCurrentLine(&quot;&quot;) is called).

At step 5 Backspace is pressed again (because the input field did not move after step 4). LINE 33 is executed again, splitting the characters in step 4 by linefeed, popping chr(67) (letter C) at LINE 34, and discarding C. The input form field is blank just prior to pressing Backspace, causing setCurrentLine(&quot;&quot;) to be called. C is discarded from markdownContent but is re-added to the input text field.

At step 6 Enter is pressed causing the problem described in the question. Here, the characters in step 5 are joined with currentLine: (C) + Enter (the Enter key just pressed). This is where the letters BC are joined together. The original linefeed that would have separated these two characters is consumed by the call to split() at step 5 in LINE 33. LINE 27 adds a second linefeed. This is why we see two linefeeds at step 6.

Notes

There are several cases and edge cases that need to be considered before text input will behave correctly.

Code

1.    import * as React from &quot;react&quot;;
2.
3.    const { useEffect, useState } = React;
4.
5.    interface BlogWitterProps {}
6.
7.    const BlogWitter: React.FunctionComponent&lt;BlogWitterProps&gt; = ({}) =&gt; {
8.      const [markdownContent, setMarkdownContent] = useState(&quot;&quot;);
9.      const [currentLine, setCurrentLine] = useState(&quot;&quot;);
10.
11.      // on each new line, update the markdown content
12.
13.      useEffect(() =&gt; {
14.        console.log(&quot;markdownContent&quot;, markdownContent);
15.        console.log(&quot;currentLine&quot;, currentLine);
16.        let chars = [];
17.        for ( let c of markdownContent ) {
18.            chars.push( c.charCodeAt( 0 ) );
19.        }
20.        let codeString = chars.join(&#39;|&#39;);
21.        console.log( &#39;codes: &#39; + codeString );
22.      }, [currentLine, markdownContent]);
23.
24.      const handleKeyDown = (e: React.KeyboardEvent&lt;HTMLInputElement&gt;) =&gt; {
25.        if (e.key === &quot;Enter&quot;) {
26.          setMarkdownContent((prev) =&gt; {
27.            return prev + currentLine + &quot;\n&quot;;
28.          });
29.          setCurrentLine(&quot;&quot;);
30.        } else if (e.key === &quot;Backspace&quot; &amp;&amp; currentLine === &quot;&quot;) {
31.          e.preventDefault();
32.          setMarkdownContent((prev) =&gt; {
33.            const lines = prev.split(&quot;\n&quot;);
34.            const lastLine = lines.pop();
35.            console.log(&quot;lines&quot;, lines);
36.
37.            setTimeout(() =&gt; {
38.              // If the last line is not empty, update the current line state
39.              if (lastLine !== &quot;&quot;) {
40.                setCurrentLine(lastLine + &quot;\n&quot;);
41.              } else {
42.                setCurrentLine(&quot;&quot;);
43.              }
44.            }, 0);
45.
46.            return lines.join(&quot;\n&quot;);
47.          });
48.        }
49.      };
50.
51.      return (
52.        &lt;div className=&quot;&quot;&gt;
53.          &lt;div&gt;
54.            {markdownContent.split(&quot;\n&quot;).map((line, index) =&gt; {
55.              return (
56.                &lt;div key={index}&gt;{ line }&lt;/div&gt;
57.              );
58.            })}
59.          &lt;/div&gt;
60.          &lt;input
61.            value={currentLine}
62.            size={ 80 }
63.            onChange={(e) =&gt; {
64.              setCurrentLine(e.target.value);
65.            }}
66.            className=&quot;w-full resize-none outline-none text-2xl bg-transparent border border-black&quot;
67.            onKeyDown={handleKeyDown}
68.          /&gt;
69.        &lt;/div&gt;
70.      );
71.    };
72.
73.    export default BlogWitter;

huangapple
  • 本文由 发表于 2023年4月17日 11:53:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76031606.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定