【问题标题】:Pass state data to ipc function call将状态数据传递给 ipc 函数调用
【发布时间】:2022-01-26 10:08:07
【问题描述】:

问题

向渲染器发送数据的事件在使用chokidar 更改文件时触发。当文件观察器被触发并且进程将事件发送到渲染器时。

我的问题是,当EmitterEvent 被触发时,我输入了useState() 变量的当前状态,但只有初始状态被传递给我的函数。

已编辑:我的问题是我无法将更新后的data 变量传递给updateData(newData) 函数,该函数是从preload.js 内部的emitter 调用的。


问题

如何将状态变量data 传递给调用?

有没有一种方法可以更改我的 preload.js 以使 api.receive 函数返回一个字符串,而不必将函数传递给 emitter ? (更多信息请查看updateData(newData)函数)

有没有更好的方法来实现这一点?

这也可以帮助我初始化第一次渲染的数据。


preload.js

contextBridge.exposeInMainWorld(
    "api", {
        send: (channel, data) => {
            // whitelist channels
            let validChannels = ["file", "save"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            let validChannels = ["file", "save"];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        },
        

    }

electron.js

function ReadNodesFileToIpc(path) {
  fs.readFile(path, (error, data) => {
    win.webContents.send("file", data);
  });
}

接收数据的组件中的代码

 function MyForceGraphComponent(){ 
  const [data, setData] = useState({ nodes: [{ id: 0, otherinfo: [] }], links: [] });
  var isDataInittiallized = 0;
  ...
 
  function updateData (newData, data) {
    if (data.nodes.length !== 1){ 
      // do stuff

      setData({ nodes:  data.nodes, links: data.links });
    }else{
      if (!isDataInittiallized){
        setData({ nodes:  newData.nodes, links: newData.links });
        isDataInittiallized = 1;
      }
    }
  }
  ...
  useEffect(() => {  
    ...
    window.api.receive("file", (bytesArray) => {
           var newData = JSON.parse(String.fromCharCode.apply(null, bytesArray));
           updateData(newData); // Check function bellow
              
         });
    ...
  }, []);
}

updateData(newData)(我的组件函数中的一个函数)

isDataInittiallized 是组件内的一个变量,更改已传递给emitter

data 是我在 useState() 函数中的变量data 成功。所以长度保持为 1,并且它包含与第一次初始化时相同的元素。


其他信息

尝试将data 变量传递给接收函数,但没有成功。

很可能在设置发射器时,传递的函数(执行JSON.parse 的函数)正在传递,之后再也没有改变。

【问题讨论】:

  • 我假设您的问题是 updateData 可以访问 data 的旧/初始状态,而不是更新状态?
  • 是的,我想要data 的更新状态,以便检查新旧data 之间的变化。 @goto1 添加,问题是该函数是从 preloadd.js 调用的。我假设传递给`window.api.receive("file", () =>...)` 的函数就像一个变量,因此总是得到更新的data 变量
  • stackoverflow.com/questions/60126199/… 但是,您应该使用useState 代替isDataInittiallized,因为这也是您想要更新和跟踪的state
  • 是的,它正在工作。我没想到即使有一个“全局”变量不使用useState() 也会导致这种“非函数更改效果”。您是否介意将其发布为答案以标记解决方案,稍后我将尝试研究一些内部信息以了解为什么会发生这种情况并将其发布在线程中?万分感谢 ! @goto1
  • 我发布了一些改进的解决方案,请看下面。

标签: javascript reactjs d3.js electron


【解决方案1】:

由于该问题与updateData 函数中的陈旧数据有关,我建议进行以下更新:

// Simplified for the sake of brevity

function MyForceGraphComponent() {
  const [data, setData] = useState({ nodes: [{ id: 0 }] })

  // isDataInitialized needs to be tracked just as any other state
  const [isDataInitialized, setIsDataInitialized] = useState(false)

  // Wrap `updateData` in `React.useCallback` to prevent stale data
  const updateData = useCallback(
    (nextData) => {
      // skip the update, no need to update the state with existing data
      if (isDataInitialized) return;
    
      setData({ nodes: nextData.nodes })
      setIsDataInitialized(true) // set to `true` to prevent future updates
    }, 
    [isDataInitialized, setIsDataInitialized]
  )

  const handleReceivedData = useCallback(
    (bytesArray) => {
      const nextData = JSON.parse(...)
      updateData(nextData)
    }, 
    [updateData]
  )

  useEffect(() => {
    window.api.receive('file', handleReceivedData);
  }, [handleReceivedData])
}

看看这个模仿你想要做什么的例子:

【讨论】:

  • 如此干净和有用再次感谢您!
【解决方案2】:

我发现您的代码中有一些错误。当您调用 updateData(newData) 时,data 为 null,data.nodes 将不起作用。你可以修改你的代码,“如果(数据 && data.nodes && data.nodes.length !== 1)"

【讨论】:

    猜你喜欢
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    相关资源
    最近更新 更多