Col*_*rdo 24 javascript callback reactjs react-hooks
我有类似的东西:
const [loading, setLoading] = useState(false);
...
setLoading(true);
doSomething(); // <--- when here, loading is still false.
Run Code Online (Sandbox Code Playgroud)
设置状态仍然是异步的,那么等待此setLoading()调用完成的最佳方法是什么?
本setLoading()似乎并没有接受一个回调像setState()使用.
getNextPage = () => {
// This will scroll back to the top, and also trigger the prefetch for the next page on the way up.
goToTop();
if (this.state.pagesSeen.includes(this.state.page + 1)) {
return this.setState({
page: this.state.page + 1,
});
}
if (this.state.prefetchedOrders) {
const allOrders = this.state.orders.concat(this.state.prefetchedOrders);
return this.setState({
orders: allOrders,
page: this.state.page + 1,
pagesSeen: [...this.state.pagesSeen, this.state.page + 1],
prefetchedOrders: null,
});
}
this.setState(
{
isLoading: true,
},
() => {
getOrders({
page: this.state.page + 1,
query: this.state.query,
held: this.state.holdMode,
statuses: filterMap[this.state.filterBy],
})
.then((o) => {
const { orders } = o.data;
const allOrders = this.state.orders.concat(orders);
this.setState({
orders: allOrders,
isLoading: false,
page: this.state.page + 1,
pagesSeen: [...this.state.pagesSeen, this.state.page + 1],
// Just in case we're in the middle of a prefetch.
prefetchedOrders: null,
});
})
.catch(e => console.error(e.message));
},
);
};
Run Code Online (Sandbox Code Playgroud)
const getNextPage = () => {
// This will scroll back to the top, and also trigger the prefetch for the next page on the way up.
goToTop();
if (pagesSeen.includes(page + 1)) {
return setPage(page + 1);
}
if (prefetchedOrders) {
const allOrders = orders.concat(prefetchedOrders);
setOrders(allOrders);
setPage(page + 1);
setPagesSeen([...pagesSeen, page + 1]);
setPrefetchedOrders(null);
return;
}
setIsLoading(true);
getOrders({
page: page + 1,
query: localQuery,
held: localHoldMode,
statuses: filterMap[filterBy],
})
.then((o) => {
const { orders: fetchedOrders } = o.data;
const allOrders = orders.concat(fetchedOrders);
setOrders(allOrders);
setPage(page + 1);
setPagesSeen([...pagesSeen, page + 1]);
setPrefetchedOrders(null);
setIsLoading(false);
})
.catch(e => console.error(e.message));
};
Run Code Online (Sandbox Code Playgroud)
在上面,我们希望按顺序运行每个setWhatever调用.这是否意味着我们需要设置许多不同的useEffect钩子来复制这种行为?
Shu*_*tri 24
useState状态更新完成后,setter不会提供回调,就像React类组件中的setState一样。为了复制相同的行为,您可以使用Hooks componentDidUpdate在React类组件中useEffect使用类似模式的生命周期方法
useEffect 钩子将第二个参数作为值的数组,在渲染周期结束后,React需要监视这些值以进行更改。
const [loading, setLoading] = useState(false);
...
useEffect(() => {
doSomething(); // This is be executed when `loading` state changes
}, [loading])
setLoading(true);
Run Code Online (Sandbox Code Playgroud)
编辑
不同于setState,useState钩子的更新程序没有回调,但是您始终可以使用a useEffect复制上述行为。但是,您需要确定加载变化
代码的功能方法如下所示
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
Run Code Online (Sandbox Code Playgroud)
const prevLoading = usePrevious(isLoading);
useEffect(() => {
if (!prevLoading && isLoading) {
getOrders({
page: page + 1,
query: localQuery,
held: localHoldMode,
statuses: filterMap[filterBy],
})
.then((o) => {
const { orders: fetchedOrders } = o.data;
const allOrders = orders.concat(fetchedOrders);
setOrders(allOrders);
setPage(page + 1);
setPagesSeen([...pagesSeen, page + 1]);
setPrefetchedOrders(null);
setIsLoading(false);
})
.catch(e => console.error(e.message));
}
}, [isLoading, preFetchedOrders, orders, page, pagesSeen]);
const getNextPage = () => {
// This will scroll back to the top, and also trigger the prefetch for the next page on the way up.
goToTop();
if (pagesSeen.includes(page + 1)) {
return setPage(page + 1);
}
if (prefetchedOrders) {
const allOrders = orders.concat(prefetchedOrders);
setOrders(allOrders);
setPage(page + 1);
setPagesSeen([...pagesSeen, page + 1]);
setPrefetchedOrders(null);
return;
}
setIsLoading(true);
};
Run Code Online (Sandbox Code Playgroud)
等到组件重新渲染.
const [loading, setLoading] = useState(false);
useEffect(() => {
if (loading) {
doSomething();
}
}, [loading]);
setLoading(true);
Run Code Online (Sandbox Code Playgroud)
您可以通过以下方式提高清晰度:
function doSomething() {
// your side effects
// return () => { }
}
function useEffectIf(condition, fn) {
useEffect(() => condition && fn(), [condition])
}
function App() {
const [loading, setLoading] = useState(false);
useEffectIf(loading, doSomething)
return (
<>
<div>{loading}</div>
<button onClick={() => setLoading(true)}>Click Me</button>
</>
);
}
Run Code Online (Sandbox Code Playgroud)
创建了一个自定义useState钩子,其工作方式与普通useState钩子类似,只是此自定义钩子的状态更新器函数采用一个回调,该回调将在状态更新和组件重新渲染后执行。
打字稿解决方案
import { useEffect, useRef, useState } from 'react';
type OnUpdateCallback<T> = (s: T) => void;
type SetStateUpdaterCallback<T> = (s: T) => T;
type SetStateAction<T> = (newState: T | SetStateUpdaterCallback<T>, callback?: OnUpdateCallback<T>) => void;
export function useCustomState<T>(init: T): [T, SetStateAction<T>];
export function useCustomState<T = undefined>(init?: T): [T | undefined, SetStateAction<T | undefined>];
export function useCustomState<T>(init: T): [T, SetStateAction<T>] {
const [state, setState] = useState<T>(init);
const cbRef = useRef<OnUpdateCallback<T>>();
const setCustomState: SetStateAction<T> = (newState, callback?): void => {
cbRef.current = callback;
setState(newState);
};
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
}
cbRef.current = undefined;
}, [state]);
return [state, setCustomState];
}
Run Code Online (Sandbox Code Playgroud)
JavaScript 解决方案
import { useEffect, useRef, useState } from 'react';
export function useCustomState(init) {
const [state, setState] = useState(init);
const cbRef = useRef();
const setCustomState = (newState, callback) => {
cbRef.current = callback;
setState(newState);
};
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
}
cbRef.current = undefined;
}, [state]);
return [state, setCustomState];
}
Run Code Online (Sandbox Code Playgroud)
用法
import { useEffect, useRef, useState } from 'react';
type OnUpdateCallback<T> = (s: T) => void;
type SetStateUpdaterCallback<T> = (s: T) => T;
type SetStateAction<T> = (newState: T | SetStateUpdaterCallback<T>, callback?: OnUpdateCallback<T>) => void;
export function useCustomState<T>(init: T): [T, SetStateAction<T>];
export function useCustomState<T = undefined>(init?: T): [T | undefined, SetStateAction<T | undefined>];
export function useCustomState<T>(init: T): [T, SetStateAction<T>] {
const [state, setState] = useState<T>(init);
const cbRef = useRef<OnUpdateCallback<T>>();
const setCustomState: SetStateAction<T> = (newState, callback?): void => {
cbRef.current = callback;
setState(newState);
};
useEffect(() => {
if (cbRef.current) {
cbRef.current(state);
}
cbRef.current = undefined;
}, [state]);
return [state, setCustomState];
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11953 次 |
| 最近记录: |