setState(updater, callback)
适用于useState
以下代码实现与类的原始setState
回调非常接近。
对已接受的答案进行了改进:
- 在初始渲染时省略了回调执行 - 我们只想在状态更新时调用它
- 每个
setState
调用的回调可以是动态的,就像使用类一样
用法
const App = () => {
const [state, setState] = useStateCallback(0);
const handleClick = () => {
setState(
prev => prev + 1,
s => console.log("I am called after setState, state:", s)
);
};
return <button onClick={handleClick}>Increment</button>;
}
useStateCallback
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null); // init mutable ref container for callbacks
const setStateCallback = useCallback((state, cb) => {
cbRef.current = cb; // store current, passed callback in ref
setState(state);
}, []); // keep object reference stable, exactly like `useState`
useEffect(() => {
// cb.current is `null` on initial render,
// so we only invoke callback on state *updates*
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null; // reset callback after execution
}
}, [state]);
return [state, setStateCallback];
}
function useStateCallback<T>(
initialState: T
): [T, (state: T, cb?: (state: T) => void) => void] {
const [state, setState] = useState(initialState);
const cbRef = useRef<((state: T) => void) | undefined>(undefined);
const setStateCallback = useCallback((state: T, cb?: (state: T) => void) => {
cbRef.current = cb;
setState(state);
}, []);
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
cbRef.current = undefined;
}
}, [state]);
return [state, setStateCallback];
}
更多信息:React Hooks FAQ:是否有类似实例变量的东西?
工作示例
const App = () => {
const [state, setState] = useStateCallback(0);
const handleClick = () =>
setState(
prev => prev + 1,
s => console.log("I am called after setState, state:", s)
);
return (
<div>
<p>Hello Comp. State: {state} </p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
function useStateCallback(initialState) {
const [state, setState] = useState(initialState);
const cbRef = useRef(null);
const setStateCallback = useCallback((state, cb) => {
cbRef.current = cb;
setState(state);
}, []);
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
cbRef.current = null;
}
}, [state]);
return [state, setStateCallback];
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<script>var { useReducer, useEffect, useState, useRef, useCallback } = React</script>
<div id="root"></div>
setName
方法并从子组件中调用它? - dan-klassongetChildChange
。将其更改为props.getChildChange(ele.target.value)
将解决此问题。请参阅 https://dev59.com/blQI5IYBdhLWcg3w8wSR#56267744 - steinybot