我如何在React Functional Component去抖动的回调中获取实际的prop值,它在React Class Component中起作用,但是我不知道如何使用钩子在功能组件中实现此行为。
import React from "react";
import ReactDOM from "react-dom";
import debounce from "lodash.debounce";
const TestFunc = ({ count, onClick }) => {
const handleClick = debounce(() => {
onClick();
console.log(count);
}, 500);
return (
<div>
<button type="button" onClick={handleClick}>
Func: {count}
</button>
</div>
);
};
class TestClass extends React.Component {
handleClick = debounce(() => {
this.props.onClick();
console.log(this.props.count);
}, 500);
render() {
return (
<div>
<button type="button" onClick={this.handleClick}>
Class: {this.props.count}
</button>
</div>
);
}
}
const App = () => {
const [countClass, setCountClass] = React.useState(0);
const [countFunc, setCountFunc] = React.useState(0);
return (
<div>
<TestFunc count={countFunc} onClick={() => setCountFunc(countFunc + 1)} />
<TestClass
count={countClass}
onClick={() => setCountClass(countClass + 1)}
/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
当您单击功能组件按钮时,它将先前的count
属性值记录到控制台,但是通过调用onClick
处理程序已将其更改,同时类组件按钮将记录实际的由count
处理程序递增后的onClick
道具值。那么,如何获取功能组件中的实际prop值?
答案 0 :(得分:3)
这是一个简单的防抖钩(用TypeScript编写)
import { useEffect, useRef } from "react";
export function useDebouncedCallback<A extends any[]>(
callback: (...args: A) => void,
wait: number
) {
// track args & timeout handle between calls
const argsRef = useRef<A>();
const timeout = useRef<ReturnType<typeof setTimeout>>();
function cleanup() {
if(timeout.current) {
clearTimeout(timeout.current);
}
}
// make sure our timeout gets cleared if
// our consuming component gets unmounted
useEffect(() => cleanup, []);
return function debouncedCallback(
...args: A
) {
// capture latest args
argsRef.current = args;
// clear debounce timer
cleanup();
// start waiting again
timeout.current = setTimeout(() => {
if(argsRef.current) {
callback(...argsRef.current);
}
}, wait);
};
}
您的用例示例:
const handleClick = useDebouncedCallback(() => {
onClick();
console.log(count);
}, 500);
...
<button type="button" onClick={handleClick}>
Func: {count}
</button>
也适用于传递参数的情况:
const handleChange = useDebouncedCallback((event) => {
console.log(event.currentTarget.value);
}, 500);
<input onChange={handleChange}/>
答案 1 :(得分:1)
您需要进行一些更改才能将debounced method
与钩子一起使用
useCallback
钩子,以便在初始渲染时仅创建一次去抖动功能。setCountFunc(count => count + 1)
)来更新onClick方法调用上的计数值,以便子组件使用更新后的值重新呈现下面的工作演示
const TestFunc = ({ count, onClick }) => {
const handleClick = React.useCallback((count) =>{
const click = _.debounce((count) => {
onClick();
console.log(count);
}, 500)
click(count);
}, []);
console.log(count, 'render');
return (
<div>
<button type="button" onClick={() => handleClick(count)}>
Func: {count}
</button>
</div>
);
};
class TestClass extends React.Component {
handleClick = _.debounce(() => {
this.props.onClick();
console.log(this.props.count);
}, 500);
render() {
return (
<div>
<button type="button" onClick={this.handleClick}>
Class: {this.props.count}
</button>
</div>
);
}
}
const App = () => {
const [countClass, setCountClass] = React.useState(0);
const [countFunc, setCountFunc] = React.useState(0);
return (
<div>
<TestFunc count={countFunc} onClick={() => setCountFunc(count => count + 1)} />
<TestClass
count={countClass}
onClick={() => setCountClass(countClass + 1)}
/>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root" />
答案 2 :(得分:1)
用于功能组件中的去抖动API调用
<input
type="text"
placeholder="Search"
onChange={(e) => search(e.target.value)}
/>
=========================================================================
const [typingTimeout, setTypingTimeout] = useState(0);
const search = async (value) => {
if (typingTimeout) {
clearTimeout(typingTimeout);
}
setTypingTimeout( setTimeout(() => {
goToSearch(value);
}, 1000)
);
}
const goToSearch = async (value) => {
const response = await getData(args);
}
用于类组件 与上述相同,但搜索功能有所改变
const search = (event.target.value) =>{
if (this.state.typingTimeout) {
clearTimeout(this.state.typingTimeout);
}
this.setState({
typingTimeout: setTimeout(()=> {
this.goToSearch(event.target.value);
}, 1000)
});
}