在 React 中,flushSync() 是做什么的?

Moh*_*deh 24 reactjs react-dom

我在 JSConf 冰岛看到了 Dan Abramov 的演示项目,但我不明白他为什么flushSync这段代码中使用:

  import { flushSync } from 'react-dom';

  debouncedHandleChange = _.debounce(value => {
    if (this.state.strategy === 'debounced') {
      flushSync(() => {
        this.setState({value: value});
      });
    }
  }, 1000);
Run Code Online (Sandbox Code Playgroud)

lushSync 在 React 中做了什么?

Chi*_*rai 21

lushSync 会刷新整个树,并实际上强制对调用内部发生的更新进行完全重新渲染,因此您应该非常谨慎地使用它。这样它就不会破坏 props、state 和 refs 之间内部一致性的保证。

\n

目前还没有正确记录。在此处阅读更多信息\n https://github.com/facebook/react/issues/11527

\n


Ale*_*lop 14

Chilarai 有一个很好的答案!(也许是由于回答时间和现在有更多文档)我不同意非常谨慎地使用它的想法。很多时候,它会停止需要额外不需要的 useEffect (这也违背了 Dan 建议使用 useEffect https://twitter.com/dan_abramov/status/1501737272999301121的方式)。

以下是基于 Dan Abramov 代码实现的一个很好的示例:

此代码的要求是自动滚动新消息(我当前使用此代码,它非常有效)。

之前,在这个例子中,我们无法在 setMessages 之后滚动,因为 DOM 尚未渲染并且需要一个钩子。

export default function App() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    let socket = connect();

    socket.onMessage((message) => {
      setMessages((m) => [
        ...m,
        message
      ])
    });
    
    return () => {
      socket.disconnect();
    };
  }, [])

  function scrollToLastMessage() {
    // ...
  }

  // NOTE: In order to scroll without using flushSync a unneeded hook
  useEffect(() => {
    scrollToLastMessage();
  }, [messages])
}
Run Code Online (Sandbox Code Playgroud)

之后,在这个例子中,DOM 被强制刷新同步,然后我们可以按照我们想要的顺序调用。

export default function App() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    let socket = connect();

    function scrollToLastMessage() {
      // ...
    }

    socket.onMessage((message) => {
      flushSync(() => {
        setMessages((m) => [
          ...m,
          message
        ])
      })
      scrollToLastMessage();
    });
    
    return () => {
      socket.disconnect();
    };
  }, [])
}
Run Code Online (Sandbox Code Playgroud)

此代码来自 Dan 在视频https://www.youtube.com/watch?v=uqII0AOW1NM 35:25 中的内容,我建议观看该视频!

我还强烈建议将flushSync 添加到您的工具带中!