React Hook:访问外部函数中的状态

时间:2019-11-17 10:36:45

标签: javascript reactjs asynchronous react-hooks

在React应用程序中,我想让一个函数启动一系列异步调用,然后能够在这些调用运行时更改可用于这些调用的状态。例如,我将让用户启动对5个数据文件的检索,这些数据文件可以在后台运行并耗时数分钟,但可以为他们提供中止该过程或减少文件总数的选项。

这里是关于它的外观的一个想法,但不幸的是,这种模式似乎不起作用:

function App() {
  const [halt, setHalt] = useState(false);

  return (
      ...
      <button onClick={() => longProcess(halt)}>Start</button>
      <button onClick={() => setHalt(true)}>Stop</button>
      ...
  );
}

async function longProcess(halt) {
  for (const fileid of files_to_get) {
    // For example, halt if the user clicks the Stop button during execution
    if (halt) break;
    await getDataFile(fileid);
  }
}

理想情况下,我想使用纯功能组件,并允许异步功能供多个组件使用。所以我一直在使用React Hooks。我已经提出了3个解决方案,但没有一个完全符合要求:

  • 使用类组件,this.state将异步更新
    • Example
    • 缺点:不是功能组件,异步功能已绑定到该组件
  • useRef()a suggested option
    • Example
    • 缺点:我们不再获得重新渲染,这是一种常见的useRef模式吗?
  • 从useState传递setter,在调用它时传递一个函数,该函数将检索当前值
    • Example
    • 缺点:似乎很hacky:)

我想知道是否有类似于第三个示例的简洁方法,我只是在有限的React经验中没有遇到过。其他建议也欢迎!

2 个答案:

答案 0 :(得分:1)

要具有可重用的功能,我将在挂钩中对其进行定义。

以下提议使用useState执行该功能。当值更改时,我们需要useState来触发渲染。此值将从useEffect内部调用该函数。

它还使用useRef,以便进程可以启动并稍后读取其值,该值在执行期间可能已更改。

const App = () => {
    const { startProcess, stopProcess } = useLongProcess();

    return (
        <Fragment>
            <button onClick={startProcess}>Start</button>
            <button onClick={stopProcess}>Stop</button>
        </Fragment>
    );
};

const useLongProcess = () => {
    const stop = useRef(false);
    const [start_process, setStartProcess] = useState(false);

    useEffect(() => {
        if (!start_process) {
            return;
        }

        const longProcess = async () => {
            for (const fileid of files_to_get) {
                if (stop.current) break;
                await getDataFile(fileid);
            }
        };

        longProcess();
    }, [start_process]);

    return {
        startProcess: () => setStartProcess(true),
        stopProcess: () => {
            stop.current = true;
        }
    };
};

答案 1 :(得分:0)

现在,一旦调用halt函数内的longProcess状态,就无法对其进行更新。因此,您可以使用某些global对象来更新状态,但这不是最佳实践。

因此,也许看一下React的useCallback和其他钩子,也许将循环更改为递归调用这些钩子之一,这样也许可以帮助更新状态。希望这会有所帮助,即使我现在还不知道解决方案。