React中,useState中的字符串更新不如预期般有效。

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

React, Update String in useState does not work as expected

问题

我想制作一个打字效果,但第二个字母没有被添加。

例如:

我想写“Hello World”,但它显示为“Hllo World”。

我的代码:

export default function Error({ errorMsg }) {
	const [errorString, setErrorString] = useState("");
	let i = 0;

	useEffect(() => {
		writeError();
	}, []);

	function writeError() {
		let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

		setTimeout(() => {
			if (i < errorMsg.length) {
				setErrorString(errorString => ([
					...errorString,
					errorMsg.charAt(i)
				]));
				i++;
				return writeError();
			}
		}, timer);
	}

	return (
		<div>
			<div id="wrp">
				<div>{errorString}</div>
			</div>
		</div>
	);
}

为什么错误只发生在第二个字符,而不管字符串有多长?

编辑

感谢提供的解决方案,但我认为@DecPK的解决方案是最好的。

修复后的代码:

export default function Error({ errorMsg }) {
	const [errorString, setErrorString] = useState("");
	let i = 0;

	useEffect(() => {
		writeError();
	}, []);

	function writeError() {
		let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

		setTimeout(() => {
			if (i < errorMsg.length) {
				setErrorString(errorString => ([
					...errorString,
					errorMsg.charAt(i++) // <-- 来自@DecPK的答案
				]));
				return writeError();
			}
		}, timer);
	}

	return (
		<div>
			<div id="wrp">
				<div>{errorString}</div>
			</div>
		</div>
	);
}
英文:

I want to make a typing efect, but the 2nd letter is not added.

For example:

I want to write "Hello World" and it displays "Hllo World".

my code:

export default function Error({ errorMsg }) {
	const [errorString, setErrorString] = useState(&quot;&quot;);
	let i = 0;

	useEffect(() =&gt; {
		writeError();
	}, []);

	function writeError() {
		let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

		setTimeout(() =&gt; {
			if (i &lt; errorMsg.length) {
				setErrorString(errorString =&gt; ([
					...errorString,
					errorMsg.charAt(i)
				]));
				i++;
				return writeError();
			}
		}, timer);
	}

	return (
		&lt;div&gt;
			&lt;div id=&quot;wrp&quot;&gt;
				&lt;div&gt;{errorString}&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	);
}

Why does the error only occur with the 2nd character, no matter how long the string is?

Edit

Thanks for the solutions, but the solution of @DecPK is the best in my opinion

fixed code:

export default function Error({ errorMsg }) {
	const [errorString, setErrorString] = useState(&quot;&quot;);
	let i = 0;

	useEffect(() =&gt; {
		writeError();
	}, []);

	function writeError() {
		let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

		setTimeout(() =&gt; {
			if (i &lt; errorMsg.length) {
				setErrorString(errorString =&gt; ([
					...errorString,
					errorMsg.charAt(i++) // &lt;-- Answer from @DecPK
				]));
				return writeError();
			}
		}, timer);
	}

	return (
		&lt;div&gt;
			&lt;div id=&quot;wrp&quot;&gt;
				&lt;div&gt;{errorString}&lt;/div&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	);
}

答案1

得分: 0

在React中,使用useState来更新字符串的问题在于,你不能像更新数字或布尔值等其他类型那样直接更新字符串。字符串是不可变的,这意味着一旦创建,就不能被修改。因此,对字符串变量的任何更新都会创建一个新的字符串,并将其分配给该变量。

要在useState中更新字符串,你可以使用useState钩子提供的set函数,将新的字符串值作为参数传递进去。例如:

const [myString, setMyString] = useState('Hello world');

// 使用set函数更新字符串值
setMyString('Hello React');

在上面的例子中,setMyString函数将myString状态变量的值更新为'Hello React'。当使用setMyString来更新字符串值时,确保始终将新的字符串作为参数传递进去,即使它与先前的字符串具有相同的值。这是因为React只会在状态值引用发生变化时重新渲染组件。

以下是在按钮点击时使用setMyString更新字符串值的示例:

function MyComponent() {
  const [myString, setMyString] = useState('Hello world');

  function handleClick() {
    setMyString('Hello React');
  }

  return (
    <div>
      <p>{myString}</p>
      <button onClick={handleClick}>Update string</button>
    </div>
  );
}

在这个例子中,点击"Update string"按钮会将myString状态变量更新为'Hello React',并导致组件以新的字符串值重新渲染。

英文:

The issue with updating a string in useState in React is that you cannot update a string directly like you can with other types such as numbers or booleans. Strings are immutable, meaning that once they are created, they cannot be modified. Therefore, any updates to a string variable create a new string and assign it to the variable.

To update a string in useState, you can use the set function provided by the useState hook, passing in the new string value as an argument. For example:

const [myString, setMyString] = useState(&#39;Hello world&#39;);

// Updating the string value using set function
setMyString(&#39;Hello React&#39;);

In the example above, the setMyString function updates the value of the myString state variable to 'Hello React'. When using setMyString to update the string value, you should make sure to always pass a new string as the argument, even if it has the same value as the previous string. This is because React will only re-render the component if the state value reference changes.

Here's an example of updating a string value using setMyString in response to a button click:

function MyComponent() {
  const [myString, setMyString] = useState(&#39;Hello world&#39;);

  function handleClick() {
    setMyString(&#39;Hello React&#39;);
  }

  return (
    &lt;div&gt;
      &lt;p&gt;{myString}&lt;/p&gt;
      &lt;button onClick={handleClick}&gt;Update string&lt;/button&gt;
    &lt;/div&gt;
  );
}

In this example, clicking the "Update string" button will update the myString state variable to 'Hello React' and cause the component to re-render with the new string value.

答案2

得分: 0

以下是您提供的代码的中文翻译部分:

import { useState, useEffect } from "react";

export default function Error({ errorMsg }) {
    const [errorString, setErrorString] = useState("");
    let i = 0;

    useEffect(() => {
        const interval = setInterval(() => writeError(), 200);
        return () => clearInterval(interval);
    }, []);

    function writeError() {
        setErrorString(errorMsg.substring(0, i));
        i++;
    }

    return (
        <div>
            <div id="wrp">
                <div>{errorString}</div>
            </div>
        </div>
    );
}

请尝试执行这段代码。

英文:

My Answer:

import { useState, useEffect } from &quot;react&quot;;

export default function Error({ errorMsg }) {
    const [errorString, setErrorString] = useState(&quot;&quot;);
    let i = 0;


    useEffect(() =&gt; {
        const interval = setInterval(() =&gt; writeError(), 200);
        return () =&gt; clearInterval(interval);
    }, []);

    function writeError() {
        setErrorString(errorMsg.substring(0, i));
        i++;
    }

    return (
        &lt;div&gt;
            &lt;div id=&quot;wrp&quot;&gt;
                &lt;div&gt;{errorString}&lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    );
}

Please try to execute this.

答案3

得分: 0

请考虑以下解决方案。此组件负责管理其cursor状态。然后,它使用errorMsg属性计算要在渲染中显示的文本。这是React的方式。
Sandbox演示可用

export function Error({ errorMsg }) {
  const [cursor, setCursor] = React.useState(0);
  const randomDelay = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

  React.useEffect(() => {
    if (!(cursor <= errorMsg.length)) return;
    const id = setTimeout(() => setCursor(cursor + 1), randomDelay);
    return () => clearTimeout(id);
  }, [cursor, errorMsg.length, randomDelay]);

  return (
    <div>
      <div id="wrp">
        <div>{errorMsg.substr(0, cursor)}</div>
      </div>
    </div>
  );
}
英文:

Please consider the solution below. This component is responsible for managing it's cursor state. It then calculates the text to show in render using the errorMsg prop. This is the React way.
Sandbox demo available

<!-- language: lang-js -->

export function Error({ errorMsg }) {
  const [cursor, setCursor] = React.useState(0);
  const randomDelay = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

  React.useEffect(() =&gt; {
    if (!(cursor &lt;= errorMsg.length)) return;
    const id = setTimeout(() =&gt; setCursor(cursor + 1), randomDelay);
    return () =&gt; clearTimeout(id);
  }, [cursor, errorMsg.length, randomDelay]);

  return (
    &lt;div&gt;
      &lt;div id=&quot;wrp&quot;&gt;
        &lt;div&gt;{errorMsg.substr(0, cursor)}&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

<!-- end snippet -->

答案4

得分: 0

以下是@DecPK的答复:

这是一个React函数组件,用于以打字效果呈现错误消息。以下是代码的注释版本:

// 导入React以及useState和useEffect钩子
import React, { useState, useEffect } from "react";

// 将Error组件定义为此模块的默认导出
export default function Error({ errorMsg }) {

  // 定义状态变量"errorString"和一个函数"setErrorString"来更新它
  const [errorString, setErrorString] = useState("");

  // 定义变量"i"来跟踪当前正在输入的字符的索引
  let i = 0;

  // 使用useEffect钩子,在组件首次挂载时触发writeError函数
  useEffect(() => {
    writeError();
  }, []);

  // 定义writeError函数,以每隔几毫秒更新errorString状态变量的方式
  function writeError() {

    // 生成一个在25毫秒和100毫秒之间的随机超时
    let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

    // 使用setTimeout函数等待随机超时,然后更新errorString状态变量的下一个字符
    setTimeout(() => {

      // 检查是否还有更多字符需要输入
      if (i < errorMsg.length) {

        // 通过将下一个字符附加到它来更新errorString状态变量
        setErrorString(errorString => ([
          ...errorString,
          errorMsg.charAt(i++) // 获取当前索引处的字符并递增i
        ]));

        // 再次调用writeError函数,以在另一个随机超时后输入下一个字符
        return writeError();
      }
    }, timer);
  }

  // 通过返回一个带有id "wrp"的div和另一个div来呈现组件,用于显示errorString状态变量
  return (
    <div>
      <div id="wrp">
        <div>{errorString}</div>
      </div>
    </div>
  );
}

总之,该组件使用useState和useEffect钩子以打字效果更新错误消息,使用setTimeout函数等待每个字符之间的随机超时。

英文:

Answer from @DecPK

This is a React functional component that renders an error message with a typing effect. Here is a commented version of the code:

// Import React and the useState and useEffect hooks
import React, { useState, useEffect } from &quot;react&quot;;

// Define the Error component as the default export of this module
export default function Error({ errorMsg }) {

  // Define a state variable &quot;errorString&quot; and a function &quot;setErrorString&quot; to update it
  const [errorString, setErrorString] = useState(&quot;&quot;);

  // Define a variable &quot;i&quot; to keep track of the index of the current character being typed
  let i = 0;

  // Use the useEffect hook to trigger the writeError function once, when the component is first mounted
  useEffect(() =&gt; {
    writeError();
  }, []);

  // Define the writeError function to update the errorString state variable with a new character every few milliseconds
  function writeError() {

    // Generate a random timeout between 25ms and 100ms
    let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

    // Use the setTimeout function to wait for the random timeout before updating the errorString state variable with the next character
    setTimeout(() =&gt; {

      // Check if there are more characters to type
      if (i &lt; errorMsg.length) {

        // Update the errorString state variable by appending the next character to it
        setErrorString(errorString =&gt; ([
          ...errorString,
          errorMsg.charAt(i++) // Get the character at the current index and increment i
        ]));

        // Call the writeError function again to type the next character after another random timeout
        return writeError();
      }
    }, timer);
  }

  // Render the component by returning a div with an id &quot;wrp&quot; and another div that displays the errorString state variable
  return (
    &lt;div&gt;
      &lt;div id=&quot;wrp&quot;&gt;
        &lt;div&gt;{errorString}&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

In summary, this component uses the useState and useEffect hooks to update the error message with a typing effect, using the setTimeout function to wait for a random timeout between each character.

huangapple
  • 本文由 发表于 2023年2月24日 17:23:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75554747.html
匿名

发表评论

匿名网友

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

确定