You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Textarea中实现防抖?解决输入延迟问题

解决React输入防抖导致的延迟问题

你遇到的核心矛盾是:防抖setCommentBody会让组件状态延迟更新,导致textarea显示跟不上输入节奏。要兼顾实时输入显示和减少重渲染,可以通过分离「实时输入存储」和「防抖状态更新」来解决:

具体实现步骤

  1. 使用useRef存储实时输入值,保证textarea能实时显示用户输入的内容
  2. 对setCommentBody进行防抖,仅在用户停止输入一段时间后更新组件状态,减少重渲染次数
  3. 清理防抖函数,避免组件卸载后残留执行逻辑

修改后的完整代码

import { debounce } from "lodash";
import { useState, useRef, useCallback, useEffect } from "react";
import ReviewCard from "../ReviewCard/ReviewCard";

const CommentInput = ({ postId, userId, onCommentChange, onCommentSubmit }) => {
  const dispatch = useDispatch();
  const [commentBody, setCommentBody] = useState("");
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [submittedText, setSubmittedText] = useState("");
  const [submittedComments, setSubmittedComments] = useState([]);
  const inputRef = useRef(""); // 存储实时输入值

  console.log(commentBody); // 现在只会在停止输入300ms后打印

  // 用useCallback包裹防抖函数,避免每次重渲染创建新实例
  const debouncedUpdateCommentBody = useCallback(
    debounce((value) => {
      setCommentBody(value);
    }, 300),
    []
  );

  const handleInputChange = (e) => {
    const value = e.target.value;
    inputRef.current = value; // 实时更新ref,保证textarea显示最新内容
    debouncedUpdateCommentBody(value); // 防抖更新组件状态
  };

  // 组件卸载时清理防抖函数
  useEffect(() => {
    return () => debouncedUpdateCommentBody.cancel();
  }, [debouncedUpdateCommentBody]);

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setIsSubmitting(true);
    // 提交时直接用ref的实时值,避免依赖延迟更新的state
    const submitValue = inputRef.current;
    const newComment = await dispatch(
      postComment({ body: submitValue, postId, userId })
    );

    setSubmittedText(submitValue);
    setIsSubmitting(false);
    onCommentChange("");

    onCommentSubmit(newComment.payload);
    setSubmittedComments([...submittedComments, newComment]);
    // 重置state和ref
    setCommentBody("");
    inputRef.current = "";
  };

  return (
    <div className={st.add_comment}>
      {submittedComments.map((comment, index) => (
        <ReviewCard
          key={index}
          reviewerName={`@${comment.payload.user.username}`}
          commentary={submittedText}
        />
      ))}

      <Text type={"h3"}>
        Add <span className={st.highlight}> comment </span>
      </Text>
      <form className={st.add_comment_form} onSubmit={handleSubmit}>
        <textarea
          className={st.add_comment_input}
          ref={inputRef}
          defaultValue={commentBody}
          onChange={handleInputChange}
          placeholder="ENTER YOUR COMMENT"
          disabled={isSubmitting}
        />
        <Button type={"primary"} disabled={isSubmitting || !inputRef.current.trim()}>
          {isSubmitting ? "Posting..." : "Send"}
        </Button>
      </form>
    </div>
  );
};

export default CommentInput;

关键说明

  • 用inputRef实时同步用户输入,textarea使用非受控模式(defaultValue),保证输入显示无延迟
  • 防抖仅作用于setCommentBody,组件只会在用户停止输入300ms后才重渲染,减少不必要的更新
  • 提交时直接读取inputRef.current的值,避免依赖延迟更新的commentBody状态
  • 添加防抖函数的清理逻辑,防止组件卸载后仍执行状态更新

内容的提问来源于stack exchange,提问作者aftab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:34:58