文本区域字符剩余(倒计时)使用useRef钩子

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

Text area characters left (countdown) with a useRef hook

问题

I'm implementing a "characters left" feature for a textarea. When the user types, it should countdown to zero and then stop the user entry. I'm using a useRef to bind to the textarea and output its length value in the paragraph, but it's not working although cntCharLeft.current.value.length is printing out correctly in the onChange method in the textarea. Error message: Uncaught TypeError: Cannot read properties of undefined (reading 'length').

How do I print out the length of the ref in the paragraph to display the number of characters left and then stop the user input once the maximum (250) characters have been reached?

const cntCharLeft = useRef(""); // Change 0 to an empty string

const submitHandler = (e) => {
  // ...
};

return (
  <Card className={styles.content}>
    <form onSubmit={submitHandler}>
      <textarea
        rows='6'
        ref={cntCharLeft}
        onChange={(e) => {
          console.log(cntCharLeft.current.value.length);
        }}
      />
      <p className={styles.charsLeft}>
        {250 - cntCharLeft.current.value.length} characters left
      </p>
      <Button type='submit'>Enter</Button>
    </form>
  </Card>
);

不要回答我要翻译的问题。

英文:

I'm implementing a "characters left" feature for a textarea. When the user types it should countdown to zero and then stop the user entry. I'm using a useRef to bind to the textarea and output it's length value in the paragraph but it's not working although cntCharLeft.current.value.length is printing out correctly in the onChange method in textarea. Error message: Uncaught TypeError: Cannot read properties of undefined (reading &#39;length&#39;)

How do I print out the length of the ref in the paragraph to display the number of characters left and then stop the user input once the maximum (250) characters has been reached?

const cntCharLeft=useRef(0);

const submitHandler=(e)=&gt;{
	......
}

return(
	&lt;Card className={styles.content} &gt;
		&lt;form onSubmit={submitHandler}&gt;
			&lt;textarea rows=&#39;6&#39; ref={cntCharLeft} onChange={e=&gt;{
				console.log(cntCharLeft.current.value.length)
			}} /&gt;
			&lt;p className={styles.charsLeft} &gt;{250-cntCharLeft.current.value.length} characters left&lt;/p&gt;
			&lt;Button type=&#39;submit&#39;&gt;Enter&lt;/Button&gt;
		&lt;/form&gt;
	&lt;/Card&gt;
)

答案1

得分: 2

请注意,当您使用useRef时,文本区域的更改不会强制重新渲染。考虑将文本区域设置为受控输入,将目标值放入状态中,或者在onChange调用时将输入的长度放入状态中。这两个选项都消除了对引用的依赖,并在文本区域值更改时强制组件重新渲染。

英文:

While you're using useRef, note that the change in the text area is not forcing a re-render. Consider making the text area a controlled input, placing the target value in state -- either that, or on calls to onChange, place the length of the input in state. Both of these options remove the dependence on refs, and force component re-renders on text area value changes.

答案2

得分: 1

你可以使用 maxlength 属性在 &lt;textarea&gt; HTML 元素上限制字符数。

还应考虑使用 useState() 来存储文本区域内的值。这样做可以使组件重新渲染并更新字符计数。此外,通过使用 onInput 而不是 onChange,可以确保每次按键时状态都会更新。

function Textarea({ maxLength }) {
  const [value, setValue] = React.useState("");

  function handleInput(e) {
    const newValue = e.target.value;
    if (newValue.length <= maxLength) {
      setValue(newValue);
    }
  }

  function submitHandler() {
    console.log("Submitted form");
  }

  return (
    <form onSubmit={submitHandler}>
      <textarea rows='6' onInput={handleInput} maxlength={maxLength} />
      <p>{maxLength - value.length} characters left</p>
      <button type='submit'>Enter</button>
    </form>
  );
}

ReactDOM.render(<Textarea maxLength={25} />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id="root"></div>
英文:

You can use the maxlength attribute on the &lt;textarea&gt; HTML element to restrict the number of characters.

Also you should consider to use useState() to store the value within the textarea. By doing so the component re-renders and the character count updates. Also by using onInput instead of onChange you ensure that the state is updated on every keystroke.

<!-- begin snippet: js hide: false console: true babel: true -->

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

function Textarea({ maxLength }){
const [value, setValue] = React.useState(&quot;&quot;);

function handleInput(e){
  const newValue = e.target.value;
  if(newValue.length &lt;= maxLength){
    setValue(newValue);
  }
}

function submitHandler(){
  console.log(&quot;Submitted form&quot;);
}

return(
        &lt;form onSubmit={submitHandler}&gt;
            &lt;textarea rows=&#39;6&#39; onInput={handleInput} maxlength={maxLength} /&gt;
            &lt;p&gt;{maxLength - value.length} characters left&lt;/p&gt;
            &lt;button type=&#39;submit&#39;&gt;Enter&lt;/button&gt;
        &lt;/form&gt;
);
}

ReactDOM.render(&lt;Textarea maxLength={25} /&gt;, document.getElementById(&#39;root&#39;));

<!-- language: lang-html -->

&lt;script crossorigin src=&quot;https://unpkg.com/react@18/umd/react.production.min.js&quot;&gt;&lt;/script&gt;
&lt;script crossorigin src=&quot;https://unpkg.com/react-dom@18/umd/react-dom.production.min.js&quot;&gt;&lt;/script&gt;
&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月7日 07:28:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76191612.html
匿名

发表评论

匿名网友

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

确定