为什么在 React 上下文中存储超时不起作用?

Why does storing a timeout in React context not work?

在我的根组件中,我有一个用于跟踪 API 密钥的上下文,该密钥每隔一段时间就会过期一次:

function App() {
    const [apiKey, setApiKey] = useState("");
    const [timeout, setTimeout] = useState(null);
    const apiKeyContextValue = {
        apiKey,
        setKey: setApiKey,
        timeout,
        setTimeout
    };
    return (
            <apiKeyContext.Provider value={apiKeyContextValue}>
                     <ApiKeyForm/>
            </apiKeyContext.Provider>
    );

我从 ApiKeyForm 设置了 api 键,用户只需输入一个 API 键;但是,我还想设置一个超时,一旦超时就会重置 apiKeyContextValue.apiKey

const ApiKeyForm = ()=>{
    const apiKeyContext = useContext(ApiKeyContext);
    const handleSubmit = e => {
        //sets api key = to value in form input  
        apiKeyContext.setKey(e.target[0].value);

        //dummy debug code for now
        apiKeyContext.setTimeout(()=>{
            alert('should wipe api key now');
        }, 1000) 
        
    }
    return (<form onSubmit={handleSubmit}>
                ...
            </form>)
}

我的问题是,当我提交表单时,我立即收到来自 setTimeout 的警报。为什么会这样,我该如何解决?

您从上下文中获取的 setTimeout 标识符是一个 状态 setter,而不是标准的 window.setTimeout 函数。当您将函数传递给状态 setter 时,您使用的是状态 setter 的回调形式,它将传递状态中最多 up-to-date 的值作为参数 - 例如

setSomeStateValue(mostUpToDateStateValue => {
  // code that relies on mostUpToDateStateValue

这将 运行 立即。您的代码也是如此,只是变量名称不同。

在上下文状态下有 timeoutsetTimeout 似乎对您没有任何帮助。如果您只想将状态设置为超时 ID,稍后可以 clearTimeout 调用它,请执行:

const [timeoutId, setTimeoutId] = useState(null);

传下来,然后做

apiKeyContext.setTimeoutId( // this references the state setter from context
    setTimeout(() => { // this references window.setTimeout
        alert('should wipe api key now');
    }, 1000)
);

如果您实际上不需要在上下文中存储超时 ID,那么您可以将其完全删除并在 ApiKeyForm 中执行:

setTimeout(() => { // this references window.setTimeout
    alert('should wipe api key now');
}, 1000)