它看起来像绕口令。
情况是我有一个自定义钩子,让我们在其中调用它hookFather
和其他人hookChild1
,hookChild2
......我需要的值但在完成处理并将其传递给所述钩子hookChild2
后应该返回给我的值的情况hookChild1
. 并且两个值(ofhookChild1
和hookChild2
)都将稍后在 hookFather 中进行处理。
我怎样才能建立一个他们互相等待的结构。我不能把钩子放在 useEffect 或 useMemo 里面
它看起来像绕口令。
情况是我有一个自定义钩子,让我们在其中调用它hookFather
和其他人hookChild1
,hookChild2
......我需要的值但在完成处理并将其传递给所述钩子hookChild2
后应该返回给我的值的情况hookChild1
. 并且两个值(ofhookChild1
和hookChild2
)都将稍后在 hookFather 中进行处理。
我怎样才能建立一个他们互相等待的结构。我不能把钩子放在 useEffect 或 useMemo 里面
是的,
hoodChild1
是异步的,因为它是一个 GraphQL 查询……另外,我怎样才能做一个像hookFather
异步的自定义钩子?
Hooks 与组件函数非常相似。如果钩子要启动稍后将完成的事情并更新钩子管理的状态,您可以在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
指示发生错误的错误值(在本例中为 none)还有其他方法可以返回这三条信息。例如,您可以返回一个带有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>
但基本的东西还是一样的:hook 至少有三种状态:Loading、Error 和 Success。