它看起来像绕口令。
情况是,我有一个自定义钩子,让我们称它为hookFather
,其中的其他钩子为hookChild1
、hookChild2
。。。我需要CCD_ 4的值,但在CCD_。并且(hookChild1
和hookChild2
的(这两个值稍后将在hookFather中进行处理。
我怎样才能建立一个他们相互等待的结构呢。我无法将挂钩放入useEffect或useMemo
hoodChild1
是异步的,因为它是一个GraphQL查询。。。换言之,我怎么能像hookFather
异步那样进行自定义挂钩呢?
钩子非常像组件函数。如果钩子要启动稍后将完成的操作并更新钩子管理的状态,则可以在useEffect
回调中执行此操作,并使用useState
跟踪状态。
下面是一个使用setTimeout
代替GraphQL查询的基本示例:
function useSomething(value) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [result, setResult] = useState(null);
useEffect(() => {
// Clear result, set loading, start query
setResult(null);
setLoading(true);
setError(null);
const handle = setTimeout(() => {
// Query complete, save the result and clear the loading flag
if (Math.random() < 0.333333333333333) {
// About a third of the time, fail for demonstration purposes
setError(new Error("Failed to load stuff"));
} else {
setResult(value * 2);
}
setLoading(false);
}, 500);
// Return a cleanup callback that cancels the timer if `value`
// changes or the component using this hook is unmounted
return () => {
clearTimeout(handle);
};
}, [value]);
// Return the loading flag, error, and the current result
return [loading, error, result];
}
const {useState, useEffect} = React;
function useSomething(value) {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [result, setResult] = useState(null);
useEffect(() => {
// Clear result, set loading, start query
setResult(null);
setLoading(true);
setError(null);
const handle = setTimeout(() => {
// Query complete, save the result and clear the loading flag
if (Math.random() < 0.333333333333333) {
// About a third of the time, fail for demonstration purposes
setError(new Error("Failed to load stuff"));
} else {
setResult(value * 2);
}
setLoading(false);
}, 500);
// Return a cleanup callback that cancels the timer if `value`
// changes or the component using this hook is unmounted
return () => {
clearTimeout(handle);
};
}, [value]);
// Return the loading flag, error, and the current result
return [loading, error, result];
}
const Example = () => {
const [value, setValue] = useState(1);
const [loading, error, result] = useSomething(value);
return <div>
<div>Value: {value} <input type="button" onClick={() => setValue(v => v + 1)} value="+" /></div>
<div>Result for {value}: {
loading
? <em>Loading...</em>
: error
? <strong>Error: {error.message}</strong>
: result
}</div>
</div>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
注意它是如何返回使用它的组件所需的三条信息的:
- 指示其异步工作正在进行的标志(
loading
( - 指示发生错误的错误值(在这种情况下,
null
表示无( - 结果数据
还有其他方法可以返回这三条信息。例如,您可以返回一个具有state
("loading"
、"error"
或"complete"
(和error
(如果处于错误状态(或value
(如果处于completed
状态(的对象:
const {useState, useEffect} = React;
const states = {
loading: "loading",
error: "error",
success: "success",
};
function useSomething(value) {
const [state, setState] = useState({
state: states.loading,
});
useEffect(() => {
// Clear result, set loading, start query
setState({
state: states.loading,
});
const handle = setTimeout(() => {
// Query complete, save the result and clear the loading flag
if (Math.random() < 0.333333333333333) {
// About a third of the time, fail for demonstration purposes
setState({
state: states.error,
error: new Error("Failed to load stuff"),
});
} else {
setState({
state: states.success,
value: value * 2,
});
}
}, 500);
// Return a cleanup callback that cancels the timer if `value`
// changes or the component using this hook is unmounted
return () => {
clearTimeout(handle);
};
}, [value]);
// Return the state
return state;
}
const Example = () => {
const [value, setValue] = useState(1);
const something = useSomething(value);
return <div>
<div>Value: {value} <input type="button" onClick={() => setValue(v => v + 1)} value="+" /></div>
<div>Result for {value}: {
something.state === "loading"
? <em>Loading...</em>
: something.state === "error"
? <strong>Error: {something.error.message}</strong>
: something.value
}</div>
</div>;
};
ReactDOM.render(<Example />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
但基本情况仍然相同:钩子至少有三种状态:Loading、Error和Success。