Promise 函数延迟状态变量
Promise function delays state variable
您如何正确地从 promise 函数存储值而不延迟?
我正在尝试使用 useEffect 挂钩,但我的状态仍然延迟。
这是有问题的,因为如果用户正在验证他的购物车,可能会应用错误的税。
useEffect(() => {
SalesTax.getSalesTax(country, region).then((tax) => {
setTax(tax.rate);
});
}, [region]);
<RegionDropdown
country={country}
className="capitalize input"
value={region}
onChange={(val) => {
setRegion(val);
}}
required
countryValueType="short"
valueType="short"
/>
你应该这样做:
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
SalesTax.getSalesTax(country, region).then((tax) => {
setTax(tax.rate);
setLoading(false);
});
}, [region]);
if (loading) {
return <p>Loading...<p/>;
}
这是在 React 中处理异步操作的正常方式。
您将使用大量异步值,那么制作一个钩子(例如 useAsync
怎么样?
function useAsync(f, [_0, _1, _2, _3, _4]) {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
setLoading(true)
Promise.resolve(f(_0, _1, _2, _3, _4))
.then(setResult, setError)
.finally(_ => setLoading(false))
}, [f, _0, _1, _2, _3, _4])
return {loading, error, result}
}
现在在你的组件中使用你的钩子 -
function MyComponent({country, region}) {
const {loading, error, result} =
useAsync(SalesTax.getSalesTax, [country, region])
if (loading)
return <p>Loading...</p>
else if (error)
return <p>Error: {error.message}</p>
else
/* result is usable here */
return <RegionDropdown .../>
}
_0
, _1
, _2
, ... 是必需的,因此 ESLint 可以静态分析依赖关系。在未来的版本中,也许可以使用数组。另一种选择是为此挂钩禁用 ESLint,但请注意这是 discouraged by Dan Abramov of React -
function useAsync(f, args) {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
setLoading(true)
Promise.resolve(f(...args))
.then(setResult, setError)
.finally(_ => setLoading(false))
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[f, ...args])
return {loading, error, result}
}
您如何正确地从 promise 函数存储值而不延迟?
我正在尝试使用 useEffect 挂钩,但我的状态仍然延迟。
这是有问题的,因为如果用户正在验证他的购物车,可能会应用错误的税。
useEffect(() => {
SalesTax.getSalesTax(country, region).then((tax) => {
setTax(tax.rate);
});
}, [region]);
<RegionDropdown
country={country}
className="capitalize input"
value={region}
onChange={(val) => {
setRegion(val);
}}
required
countryValueType="short"
valueType="short"
/>
你应该这样做:
const [loading, setLoading] = useState(false);
useEffect(() => {
setLoading(true);
SalesTax.getSalesTax(country, region).then((tax) => {
setTax(tax.rate);
setLoading(false);
});
}, [region]);
if (loading) {
return <p>Loading...<p/>;
}
这是在 React 中处理异步操作的正常方式。
您将使用大量异步值,那么制作一个钩子(例如 useAsync
怎么样?
function useAsync(f, [_0, _1, _2, _3, _4]) {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
setLoading(true)
Promise.resolve(f(_0, _1, _2, _3, _4))
.then(setResult, setError)
.finally(_ => setLoading(false))
}, [f, _0, _1, _2, _3, _4])
return {loading, error, result}
}
现在在你的组件中使用你的钩子 -
function MyComponent({country, region}) {
const {loading, error, result} =
useAsync(SalesTax.getSalesTax, [country, region])
if (loading)
return <p>Loading...</p>
else if (error)
return <p>Error: {error.message}</p>
else
/* result is usable here */
return <RegionDropdown .../>
}
_0
, _1
, _2
, ... 是必需的,因此 ESLint 可以静态分析依赖关系。在未来的版本中,也许可以使用数组。另一种选择是为此挂钩禁用 ESLint,但请注意这是 discouraged by Dan Abramov of React -
function useAsync(f, args) {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [result, setResult] = useState(null)
useEffect(_ => {
setLoading(true)
Promise.resolve(f(...args))
.then(setResult, setError)
.finally(_ => setLoading(false))
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[f, ...args])
return {loading, error, result}
}