useState() setter 不在异步函数内部触发(电子)
useState() setter not triggering inside an async function (electron)
我已经为此苦苦挣扎了一段时间,非常感谢您能给我的任何指示。
我正在为我使用可编程微控制器制作的自定义宏键盘使用 React 构建一个简单的电子应用程序。通信通过串行端口处理并按预期工作。我希望能够通过单击 GUI(有效)或直接按键盘上的实际键(无效)来 select 其中一个按钮。
更具体地说,setter 在点击时被正确调用,但在串口读取时没有被正确调用。
import './App.css';
import Key from './components/Key';
import styled from "styled-components";
import React, { useEffect, useState } from 'react';
const KeyHolder = styled.div`
display: grid;
grid-template-columns: repeat(4, 100px);
gap: 1rem;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`;
const App = () => {
const [isPortOpen, setPortOpen] = useState(false);
const [selectedKey, setSelectedKey] = useState('');
useEffect(() => console.log('selectedKey', selectedKey), [selectedKey]);
useEffect(() => console.log(isPortOpen), [isPortOpen]);
const connect = async () => {
try {
const ports = await navigator.serial.getPorts();
const port = ports[0];
await port.open({ baudRate: 9600 });
setPortOpen(true);
// eslint-disable-next-line no-undef
const decoder = new TextDecoderStream();
port.readable.pipeTo(decoder.writable);
const inputStream = decoder.readable;
const reader = inputStream.getReader();
while (true) {
const { value, done } = await reader.read();
if (value) {
console.log("key pressed: ",value); // This correctly logs the pressed key
setSelectedKey(value); // This setter does not trigger the useEffect()
}
if (done) {
console.log('DONE');
}
}
} catch (error) {
console.warn(error);
}
}
if (!isPortOpen) {
connect();
}
return (
<div className="App">
<header className="App-header">
<KeyHolder>
{/* All this setters work as intended and trigger the useEffect() */}
<Key isPressed={selectedKey === '5'} onClick={() => setSelectedKey('5')} />
<Key isPressed={selectedKey === '6'} onClick={() => setSelectedKey('6')} />
<Key isPressed={selectedKey === '7'} onClick={() => setSelectedKey('7')} />
<Key isPressed={selectedKey === '8'} onClick={() => setSelectedKey('8')} />
<Key isPressed={selectedKey === '1'} onClick={() => setSelectedKey('1')} />
<Key isPressed={selectedKey === '2'} onClick={() => setSelectedKey('2')} />
<Key isPressed={selectedKey === '3'} onClick={() => setSelectedKey('3')} />
<Key isPressed={selectedKey === '4'} onClick={() => setSelectedKey('4')} />
</KeyHolder>
</header>
</div>
);
}
export default App;
问题可能是 setter 是从异步函数中调用的吗?如果是这样的话,你能给我一些关于如何避免这个问题的资源吗?
非常感谢您。
您可以像这样将 connect() 放在 useEffect
中
useEffect(() => {
if (!isPortOpen) {
connect();
}
}, [isPortOpen])
这没有回答您的问题,但也许您会发现此 post 很有帮助。
我以前没见过 styled-components
,觉得很有趣我可以在 JavaScript 的 单行 行中替换 33,500 Bytes package with 10 dependencies , styled
下面.
function styled(Tag, style = {}) {
return props => <Tag style={style} {...props} />
}
const Foo = styled("div", {backgroundColor: "blue", padding: "1rem" })
const Big = styled("button", {fontSize: "3rem"})
function App() {
return <Foo>
<Big onClick={e => console.log("hello")}>
Hello
</Big>
</Foo>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.development.js"></script>
<div id="app"></div>
我已经为此苦苦挣扎了一段时间,非常感谢您能给我的任何指示。
我正在为我使用可编程微控制器制作的自定义宏键盘使用 React 构建一个简单的电子应用程序。通信通过串行端口处理并按预期工作。我希望能够通过单击 GUI(有效)或直接按键盘上的实际键(无效)来 select 其中一个按钮。
更具体地说,setter 在点击时被正确调用,但在串口读取时没有被正确调用。
import './App.css';
import Key from './components/Key';
import styled from "styled-components";
import React, { useEffect, useState } from 'react';
const KeyHolder = styled.div`
display: grid;
grid-template-columns: repeat(4, 100px);
gap: 1rem;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`;
const App = () => {
const [isPortOpen, setPortOpen] = useState(false);
const [selectedKey, setSelectedKey] = useState('');
useEffect(() => console.log('selectedKey', selectedKey), [selectedKey]);
useEffect(() => console.log(isPortOpen), [isPortOpen]);
const connect = async () => {
try {
const ports = await navigator.serial.getPorts();
const port = ports[0];
await port.open({ baudRate: 9600 });
setPortOpen(true);
// eslint-disable-next-line no-undef
const decoder = new TextDecoderStream();
port.readable.pipeTo(decoder.writable);
const inputStream = decoder.readable;
const reader = inputStream.getReader();
while (true) {
const { value, done } = await reader.read();
if (value) {
console.log("key pressed: ",value); // This correctly logs the pressed key
setSelectedKey(value); // This setter does not trigger the useEffect()
}
if (done) {
console.log('DONE');
}
}
} catch (error) {
console.warn(error);
}
}
if (!isPortOpen) {
connect();
}
return (
<div className="App">
<header className="App-header">
<KeyHolder>
{/* All this setters work as intended and trigger the useEffect() */}
<Key isPressed={selectedKey === '5'} onClick={() => setSelectedKey('5')} />
<Key isPressed={selectedKey === '6'} onClick={() => setSelectedKey('6')} />
<Key isPressed={selectedKey === '7'} onClick={() => setSelectedKey('7')} />
<Key isPressed={selectedKey === '8'} onClick={() => setSelectedKey('8')} />
<Key isPressed={selectedKey === '1'} onClick={() => setSelectedKey('1')} />
<Key isPressed={selectedKey === '2'} onClick={() => setSelectedKey('2')} />
<Key isPressed={selectedKey === '3'} onClick={() => setSelectedKey('3')} />
<Key isPressed={selectedKey === '4'} onClick={() => setSelectedKey('4')} />
</KeyHolder>
</header>
</div>
);
}
export default App;
问题可能是 setter 是从异步函数中调用的吗?如果是这样的话,你能给我一些关于如何避免这个问题的资源吗?
非常感谢您。
您可以像这样将 connect() 放在 useEffect
中
useEffect(() => {
if (!isPortOpen) {
connect();
}
}, [isPortOpen])
这没有回答您的问题,但也许您会发现此 post 很有帮助。
我以前没见过 styled-components
,觉得很有趣我可以在 JavaScript 的 单行 行中替换 33,500 Bytes package with 10 dependencies , styled
下面.
function styled(Tag, style = {}) {
return props => <Tag style={style} {...props} />
}
const Foo = styled("div", {backgroundColor: "blue", padding: "1rem" })
const Big = styled("button", {fontSize: "3rem"})
function App() {
return <Foo>
<Big onClick={e => console.log("hello")}>
Hello
</Big>
</Foo>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.development.js"></script>
<div id="app"></div>