electron React电子应用中的状态毛刺

ix0qys7i  于 6个月前  发布在  Electron
关注(0)|答案(1)|浏览(71)

我有一个Recorder.jsx文件如下:

import { useEffect, useState } from 'react'
import { channels } from '../../../../shared'
import { Button } from 'primereact/button'

const { ipcRenderer } = electron

function Recorder() {
  const [sources, setSources] = useState([])

  const handleSources = (_, sources) => {
    setSources(sources)
  }

  const getScreenSources = () => {
    ipcRenderer.send(channels.GET_SOURCES)
  }

  useEffect(() => {
    ipcRenderer.on(channels.GET_SOURCES, handleSources)
    // Clean the listener after the component is dismounted
    return () => {
      ipcRenderer.removeAllListeners()
    }
  }, [])

  const Test = () => {
    ipcRenderer.send(channels.TEST)
  }

  const Test1 = () => {
    console.log('Test ', sources)
  }

  useEffect(() => {
    ipcRenderer.on(channels.TEST, Test1)

    return () => {
      ipcRenderer.removeAllListeners()
    }
  }, [])

  return (
    <div>
      <Button label="Test" onClick={Test} />
      <Button label="Get Sources" onClick={getScreenSources} />
      {sources &&
        sources.map((source) => {
          return <li>{source.name}</li>
        })}
    </div>
  )
}

export default Recorder

字符串
我在我的电子应用程序的main/index.js文件中有这个:

...
ipcMain.on(channels.GET_SOURCES, async (e) => {
  const inputSources = await desktopCapturer.getSources({
    types: ['window', 'screen']
  })

  e.sender.send(channels.GET_SOURCES, inputSources)
})

ipcMain.on(channels.TEST, async (e) => {
  // createRecordActionsWindow()
  e.sender.send(channels.TEST)
})
...


我点击了“获取源代码”按钮并获取了所有的源代码,它们都处于“源代码”状态,并显示为列表项。
现在,当我点击“测试”按钮和Test1函数运行,但控制台日志显示空的源数组,而不是填充数组。
我期望源数组在这里被填充。

puruo6ea

puruo6ea1#

你犯了两个常见的错误。第一个是第二个useEffect上的空依赖数组:

useEffect(() => {
  ipcRenderer.on(channels.TEST, Test1)

  return () => {
    ipcRenderer.removeAllListeners()
  }
}, [])

字符串
一个空的依赖数组意味着效果将永远不会重新运行,因此如果你在其中使用一个状态,它将保持其初始值。由于你的效果依赖于Test1,而Test1依赖于sources,你应该使用useCallback并使你的依赖匹配代码:

const Test1 = useCallback(() => {
  console.log('Test ', sources);
}, [sources]);

useEffect(() => {
  ipcRenderer.on(channels.TEST, Test1);

  return () => {
    ipcRenderer.removeAllListeners();
  }
}, [Test1]);


同样要小心这些removeAllListeners(),你实际上想要的是删除 * 仅 * 任何监听器在效果中使用,而不是 * 所有 * 监听器。为此,你应该将通道的名称传递给removeAllListeners(),或者使用removeListener()
第二个错误是,你可能不想使用send/on/on,如果你想调用main并获得响应,你可以简单地使用invoke/handle。例如:

渲染器

const getScreenSources = async () => {
  const source = await ipcRenderer.invoke(channels.GET_SOURCES);
  setSources(sources);
};

主要

ipcMain.handle(channels.GET_SOURCES, () => (
  desktopCapturer.getSources({
    types: ['window', 'screen']
  })
));


这也意味着useEffect s不再需要。

相关问题