将状态数据传递给 ipc 函数调用
Pass state data to ipc function call
问题
将数据发送到渲染器的事件在 chokidar
的文件更改时触发。当文件观察器被触发并且进程将事件发送到渲染器时。
我的问题是,当 EmitterEvent
被触发时,我输入 useState()
变量的当前状态,但只有初始状态被传递到我的函数。
已编辑:我的问题是我无法将更新后的 data
变量传递给从 preload.js
中的 emitter
调用的 updateData(newData)
函数。
问题
如何将状态变量 data
传递给调用?
有没有一种方法可以将 preload.js 更改为 api.receive
函数 return 字符串,从而不必将函数传递给 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() 函数的变量, 所做的更改 NOT 已传递给 emitter
即使 setData()
之前已成功更改 data
。所以长度保持为 1,并且它包含与第一次初始化时相同的元素。
其他信息
曾尝试将 data
变量传递给接收函数,但没有成功。
最有可能的是,当发射器被设置时,传递的函数(执行 JSON.parse
的函数)被传递并且之后从未改变。
我发现你的代码有一些错误。当你调用 updateData(newData) 时,data 为 null,data.nodes 将不起作用。你可以修改你的代码,“如果(数据
&& data.nodes && data.nodes.length !== 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])
}
看看这个模仿您正在尝试做的事情的例子:
问题
将数据发送到渲染器的事件在 chokidar
的文件更改时触发。当文件观察器被触发并且进程将事件发送到渲染器时。
我的问题是,当 EmitterEvent
被触发时,我输入 useState()
变量的当前状态,但只有初始状态被传递到我的函数。
已编辑:我的问题是我无法将更新后的 data
变量传递给从 preload.js
中的 emitter
调用的 updateData(newData)
函数。
问题
如何将状态变量 data
传递给调用?
有没有一种方法可以将 preload.js 更改为 api.receive
函数 return 字符串,从而不必将函数传递给 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() 函数的变量, 所做的更改 NOT 已传递给 emitter
即使 setData()
之前已成功更改 data
。所以长度保持为 1,并且它包含与第一次初始化时相同的元素。
其他信息
曾尝试将 data
变量传递给接收函数,但没有成功。
最有可能的是,当发射器被设置时,传递的函数(执行 JSON.parse
的函数)被传递并且之后从未改变。
我发现你的代码有一些错误。当你调用 updateData(newData) 时,data 为 null,data.nodes 将不起作用。你可以修改你的代码,“如果(数据 && data.nodes && data.nodes.length !== 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])
}
看看这个模仿您正在尝试做的事情的例子: