如何在React textarea中实现debounce?

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

我尝试在 React 组件中将去抖动添加到 handleInputChange 中。当用户在textarea中输入内容时,不应该不断地重新渲染(我通过console.log(commentBody)检查它,但也许我错了,我对React经验不是很丰富)但问题是它不起作用适当地。我尝试过的所有变体也会增加打字延迟,请参见下文。

import { debounce } from "lodash";
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([]);

  console.log(commentBody);

  const handleInputChange = (e) => {
    setCommentBody(e.target.value);
  };

  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setIsSubmitting(true);
    const newComment = await dispatch(
      postComment({ body: commentBody, postId, userId })
    );

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

    onCommentSubmit(newComment.payload);
    setSubmittedComments([...submittedComments, newComment]);
    setCommentBody("");
  };

  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}
          value={commentBody}
          //   onChange={(e) => setCommentBody(e.target.value)}

          onChange={handleInputChange}
          placeholder="ENTER YOUR COMMENT"
          disabled={isSubmitting}
        />
        <Button type={"primary"} disabled={isSubmitting || !commentBody.trim()}>
          {isSubmitting ? "Posting..." : "Send"}
        </Button>
      </form>
    </div>
  );
};

export default CommentInput;

我尝试这样做:

 const debouncedSave = debounce((value) => setCommentBody(value), 300); 

  const handleInputChange = (e) => {
    debouncedSave(e.target.value);
  };

但问题是它也增加了打字的延迟,这不是我需要的。

reactjs debouncing
1个回答
0
投票

如果你想要去抖,你有2个选择。

1.受控输入/文本区域

如果您想保持输入受控(通过状态控制其值),您应该使用单独的状态来存储 DEBOUNCED 值。会是这样的:

const MyComponent = () => {
    const [value, setValue] = useState("")
    const [debouncedValue, setDebouncedValue] = useState(value)
    const debounceRef = useRef<NodeJS.Timeout>(null);

    useEffect(() => {
        clearTimeout(debounceRef.current)

        debounceRef.current = setTimeout(() => setDebouncedValue(value), 300)
    }, [value])

    return <textarea value={value} />
}
2.不受控制的输入/文本区域(使用 onChange)

当我们的输入不受控制时,您也可以在不使用 2 种状态的情况下执行此操作。让我们看一下例子:

const MyComponent = () => {
    const [debouncedValue, setDebouncedValue] = useState(value)
    const debounceRef = useRef<NodeJS.Timeout>(null);

    return (
       <textarea
           defaultValue="" // you can still use defaultValue if you want (optional)
           onChange={(e) => {
               clearTimeout(debounceRef.current)

               debounceRef.current = setTimeout(() => setDebouncedValue(value), 300)
           }} 
       />
    )
}

两种解决方案都有效,但我喜欢第一个,因为我对输入有更多的控制权,并且我可以随时更改主要值。

奖励:您可以使用

@mantine/hooks
库,它公开了自定义挂钩的日志,可以在这种情况下为您提供帮助。它有 2 个可用于消除抖动的挂钩:
useDebouncedState
useDebouncedValue
。我在我的实际项目中使用它们。您可以在这里查看示例:

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