Phi*_*ume 5 javascript lodash reactjs
我目前正在努力应对反应输入并从 lodash 中去抖动。大多数情况下,当我有一个表单时,我也有一个编辑选项,所以我需要一个受控组件来填充输入,value={state["targetValue"]}以便我可以填充和编辑该字段。
但是,如果组件受到控制,则 debounce 不起作用。我在 CodeSandbox 上做了一个简单的例子:https ://codesandbox.io/embed/icy-cloud-ydzj2 ? fontsize =14& hidenavigation =1& theme = dark
代码:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import { debounce } from "lodash";
import "./styles.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: "",
title: "",
editMode: false
};
this.debouncedEvent = React.createRef();
}
debounceEvent(_fn, timer = 500, options = null) {
this.debouncedEvent.current = debounce(_fn, timer, options);
return e => {
e.persist();
return this.debouncedEvent.current(e);
};
}
componentWillUnmount() {
this.debouncedEvent.current.cancel();
}
onChangeValue = event => {
const { name, value } = event.target;
this.setState(() => {
return { [name]: value };
});
};
onRequestEdit = () => {
this.setState({ name: "Abla blabla bla", editMode: true });
};
onCancelEdit = () => {
if (this.state.editMode) this.setState({ name: "", editMode: false });
};
onSubmit = event => {
event.preventDefault();
console.log("Submiting", this.state.name);
};
render() {
const { name, editMode } = this.state;
const isSubmitOrEditLabel = editMode ? `Edit` : "Submit";
console.log("rendering", name);
return (
<div className="App">
<h1> How to debounce controlled input ?</h1>
<button type="button" onClick={this.onRequestEdit}>
Fill with dummy data
</button>
<button type="button" onClick={this.onCancelEdit}>
Cancel Edit Mode
</button>
<div style={{ marginTop: "25px" }}>
<label>
Controlled / Can be used for editing but not with debounce
</label>
<form onSubmit={this.onSubmit}>
<input
required
type="text"
name="name"
value={name}
placeholder="type something"
// onChange={this.onChangeValue}
onChange={this.debounceEvent(this.onChangeValue)}
/>
<button type="submit">{isSubmitOrEditLabel}</button>
</form>
</div>
<div style={{ marginTop: "25px" }}>
<label> Uncontrolled / Can't be used for editing </label>
<form onSubmit={this.onSubmit}>
<input
required
type="text"
name="name"
placeholder="type something"
onChange={this.debounceEvent(this.onChangeValue)}
/>
<button type="submit">{isSubmitOrEditLabel}</button>
</form>
</div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Run Code Online (Sandbox Code Playgroud)
乍一看这似乎不可能,但有一个简单的方法可以做到。只需在 React 组件外部创建 debounce 函数表达式即可。
这是一个伪示例,适用于带有 Hooks 的现代 React:
import React, { useState, useEffect } from "react";
import { debounce } from "lodash";
...
const getSearchResults = debounce((value, dispatch) => {
dispatch(getDataFromAPI(value));
}, 800);
const SearchData = () => {
const [inputValue, setInputValue] = useState("");
...
useEffect(() => {
getSearchResults(inputValue, dispatch);
}, [inputValue]);
...
return (
<>
<input
type="text"
placeholder="Search..."
value={inputValue}
onChange={e => setInputValue(e.target.value)}
/>
...
</>
);
};
export default SearchData;
Run Code Online (Sandbox Code Playgroud)
更新:及时我使用“useCallback”想出了一个更好的解决方案
import React, { useState, useEffect, useCallback } from "react";
import { debounce } from "lodash";
...
const SearchData = () => {
const [inputValue, setInputValue] = useState("");
...
const getSearchResults = useCallback(
debounce(value => {
dispatch(getDataFromAPI(value));
}, 800),
[]
);
useEffect(() => {
getSearchResults(inputValue);
}, [inputValue]);
...
return (
<>
<input
type="text"
placeholder="Search..."
value={inputValue}
onChange={e => setInputValue(e.target.value)}
/>
...
</>
);
};
Run Code Online (Sandbox Code Playgroud)
所以……显然,没有解决办法。输入从状态获取值。而去抖会阻止状态触发。
我使用 ReactDOM 做了一个解决方法。
import ReactDOM from "react-dom";
export const setFormDefaultValue = (obj, ref) => {
if (ref && !ref.current) return;
if (!obj || !obj instanceof Object) return;
const _this = [
...ReactDOM.findDOMNode(ref.current).getElementsByClassName("form-control")
];
if (_this.length > 0) {
_this.forEach(el => {
if (el.name in obj) el.value = obj[el.name];
else console.error(`Object value for ${el.name} is missing...`);
});
}
};
Run Code Online (Sandbox Code Playgroud)
然后使用:
this.refForm = React.createRef();
setFormDefaultValue(this.state, refForm)
Run Code Online (Sandbox Code Playgroud)
这样我就可以用状态默认值填写表单并继续使用去抖。
| 归档时间: |
|
| 查看次数: |
3502 次 |
| 最近记录: |