我尝试在 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);
};
但问题是它也增加了打字的延迟,这不是我需要的。
如果你想要去抖,你有2个选择。
如果您想保持输入受控(通过状态控制其值),您应该使用单独的状态来存储 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 种状态的情况下执行此操作。让我们看一下例子:
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
。我在我的实际项目中使用它们。您可以在这里查看示例: