【发布时间】:2022-01-13 01:47:50
【问题描述】:
我在这里有一个输入字段,在每种类型上,它都会调度一个 redux 操作。
我放了一个 useDebounce 以使它不会很重。问题是它说Hooks can only be called inside of the body of a function component. 正确的做法是什么?
使用超时
import { useCallback, useEffect, useRef } from "react";
export default function useTimeout(callback, delay) {
const callbackRef = useRef(callback);
const timeoutRef = useRef();
useEffect(() => {
callbackRef.current = callback;
}, [callback]);
const set = useCallback(() => {
timeoutRef.current = setTimeout(() => callbackRef.current(), delay);
}, [delay]);
const clear = useCallback(() => {
timeoutRef.current && clearTimeout(timeoutRef.current);
}, []);
useEffect(() => {
set();
return clear;
}, [delay, set, clear]);
const reset = useCallback(() => {
clear();
set();
}, [clear, set]);
return { reset, clear };
}
使用去抖动
import { useEffect } from "react";
import useTimeout from "./useTimeout";
export default function useDebounce(callback, delay, dependencies) {
const { reset, clear } = useTimeout(callback, delay);
useEffect(reset, [...dependencies, reset]);
useEffect(clear, []);
}
表单组件
import React from "react";
import TextField from "@mui/material/TextField";
import useDebounce from "../hooks/useDebounce";
export default function ProductInputs(props) {
const { handleChangeProductName = () => {} } = props;
return (
<TextField
fullWidth
label="Name"
variant="outlined"
size="small"
name="productName"
value={formik.values.productName}
helperText={formik.touched.productName ? formik.errors.productName : ""}
error={formik.touched.productName && Boolean(formik.errors.productName)}
onChange={(e) => {
formik.setFieldValue("productName", e.target.value);
useDebounce(() => handleChangeProductName(e.target.value), 1000, [
e.target.value,
]);
}}
/>
);
}
【问题讨论】:
-
是的,这绝对是放置钩子的错误位置。钩子应该放置在渲染元素之外。将其移动到
TextField的父组件主体内 -
你的钩子是从你的组件内部的一个函数中调用的,这违反了hooks的规则你应该在顶层使用钩子。
-
@smac89。那么你将如何移动它并从中调用呢?
-
您自己定义了
useDebounce吗?你打算如何使用它? -
@Bergi。更新了我的问题。我想使用
handleChangeProductName向redux 发送一个动作,而不是在每个输入上,因为我有很多文本字段,所以它会很重
标签: javascript reactjs ecmascript-6 react-hooks debouncing