1

它看起来像绕口令。

情况是我有一个自定义钩子,让我们在其中调用它hookFather和其他人hookChild1hookChild2......我需要的值但在完成处理并将其传递给所述钩子hookChild2后应该返回给我的值的情况hookChild1. 并且两个值(ofhookChild1hookChild2)都将稍后在 hookFather 中进行处理。

我怎样才能建立一个他们互相等待的结构。我不能把钩子放在 useEffect 或 useMemo 里面

4

1 回答 1

0

是的,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。

于 2022-03-04T07:22:13.957 回答