集成去抖以响应 Formik 字段
Integrating debounce to respond to a Formik field
我的目标是用户可以在 websiteUrl
的输入字段中键入内容。一旦他停止输入,iFrameUrl 字段应在 2 秒后更新并显示 iFrame。但是,一旦我开始输入,它似乎会立即加载。
const IntegrationWebsite = ({
isShown,
onClose,
onSave,
integration,
...props
}) => {
const [iFrameUrl, setIFrameUrl] = useState();
const handleWebsiteUrlChange = (event, setFieldValue) => {
const value = event.target.value;
setFieldValue("websiteUrl", event.target.value);
const debouncedSave = debounce(() => setIFrameUrl(value), 1000);
debouncedSave();
};
return (
<SideSheet
title="Add Website"
isOpen={isShown}
onClose={onClose}
onSave={onSave}
initialValues={{
websiteUrl: integration?.properties.websiteUrl ?? "",
}}
validationSchema={validationSchema}
{...props}
>
{({ values, setFieldValue }) => (
<Grid container spacing={3}>
<Grid xs={12} item>
<Field
InputProps={{
onChange: (event) =>
handleWebsiteUrlChange(event, setFieldValue),
}}
required
name="websiteUrl"
label="Website URL"
component={TextField}
/>
</Grid>
<Grid xs={12} item>
<iframe
src={iFrameUrl}
height="300"
width="100%"
title="Iframe Example"
></iframe>
</Grid>
</Grid>
)}
</SideSheet>
);
};
export default IntegrationWebsite;
去抖函数,是一个带有内部超时的函数。每当您再次调用 same 函数时,计时器会重置,倒计时会再次开始。由于您在每次击键时都重新创建了 debounced 函数,因此永远不会再次调用该函数,而是调用包装函数。
const debouncedSave = debounce(() => setIFrameUrl(value), 1000);
为防止这种情况发生,您需要生成一次去抖动函数并将其记忆,以便始终使用相同的函数。
为此,将 Formik 包装器的内容提取到另一个组件。创建一个 memoized debounced 函数,并从 handleWebsiteUrlChange
.
调用它
示例(未测试):
const IntegrationField = ({ setFieldValue }) => {
const [iFrameUrl, setIFrameUrl] = useState();
const debouncedSave = useMemo(
() => debounce(value => setIFrameUrl(value), 1000),
[]
);
const onChange = useCallback(event => {
const value = event.target.value;
setFieldValue("websiteUrl", value);
debouncedSave(value);
}, [setFieldValue]);
return (
<Grid container spacing={3}>
<Grid xs={12} item>
<Field
InputProps={{ onChange }}
required
name="websiteUrl"
label="Website URL"
component={TextField}
/>
</Grid>
<Grid xs={12} item>
<iframe
src={iFrameUrl}
height="300"
width="100%"
title="Iframe Example"
></iframe>
</Grid>
</Grid>
);
};
const IntegrationWebsite = ({
isShown,
onClose,
onSave,
integration,
...props
}) => {
return (
<SideSheet
title="Add Website"
isOpen={isShown}
onClose={onClose}
onSave={onSave}
initialValues={{
websiteUrl: integration?.properties.websiteUrl ?? "",
}}
validationSchema={validationSchema}
{...props}
>
{formik => (
<IntegrationField {...formik} />
)}
</SideSheet>
);
};
export default IntegrationWebsite;
我的目标是用户可以在 websiteUrl
的输入字段中键入内容。一旦他停止输入,iFrameUrl 字段应在 2 秒后更新并显示 iFrame。但是,一旦我开始输入,它似乎会立即加载。
const IntegrationWebsite = ({
isShown,
onClose,
onSave,
integration,
...props
}) => {
const [iFrameUrl, setIFrameUrl] = useState();
const handleWebsiteUrlChange = (event, setFieldValue) => {
const value = event.target.value;
setFieldValue("websiteUrl", event.target.value);
const debouncedSave = debounce(() => setIFrameUrl(value), 1000);
debouncedSave();
};
return (
<SideSheet
title="Add Website"
isOpen={isShown}
onClose={onClose}
onSave={onSave}
initialValues={{
websiteUrl: integration?.properties.websiteUrl ?? "",
}}
validationSchema={validationSchema}
{...props}
>
{({ values, setFieldValue }) => (
<Grid container spacing={3}>
<Grid xs={12} item>
<Field
InputProps={{
onChange: (event) =>
handleWebsiteUrlChange(event, setFieldValue),
}}
required
name="websiteUrl"
label="Website URL"
component={TextField}
/>
</Grid>
<Grid xs={12} item>
<iframe
src={iFrameUrl}
height="300"
width="100%"
title="Iframe Example"
></iframe>
</Grid>
</Grid>
)}
</SideSheet>
);
};
export default IntegrationWebsite;
去抖函数,是一个带有内部超时的函数。每当您再次调用 same 函数时,计时器会重置,倒计时会再次开始。由于您在每次击键时都重新创建了 debounced 函数,因此永远不会再次调用该函数,而是调用包装函数。
const debouncedSave = debounce(() => setIFrameUrl(value), 1000);
为防止这种情况发生,您需要生成一次去抖动函数并将其记忆,以便始终使用相同的函数。
为此,将 Formik 包装器的内容提取到另一个组件。创建一个 memoized debounced 函数,并从 handleWebsiteUrlChange
.
示例(未测试):
const IntegrationField = ({ setFieldValue }) => {
const [iFrameUrl, setIFrameUrl] = useState();
const debouncedSave = useMemo(
() => debounce(value => setIFrameUrl(value), 1000),
[]
);
const onChange = useCallback(event => {
const value = event.target.value;
setFieldValue("websiteUrl", value);
debouncedSave(value);
}, [setFieldValue]);
return (
<Grid container spacing={3}>
<Grid xs={12} item>
<Field
InputProps={{ onChange }}
required
name="websiteUrl"
label="Website URL"
component={TextField}
/>
</Grid>
<Grid xs={12} item>
<iframe
src={iFrameUrl}
height="300"
width="100%"
title="Iframe Example"
></iframe>
</Grid>
</Grid>
);
};
const IntegrationWebsite = ({
isShown,
onClose,
onSave,
integration,
...props
}) => {
return (
<SideSheet
title="Add Website"
isOpen={isShown}
onClose={onClose}
onSave={onSave}
initialValues={{
websiteUrl: integration?.properties.websiteUrl ?? "",
}}
validationSchema={validationSchema}
{...props}
>
{formik => (
<IntegrationField {...formik} />
)}
</SideSheet>
);
};
export default IntegrationWebsite;