TauriでappWindow.listenを使いたいのですが、stateが更新されたタイミングで重複登録されてしまう
Q&A
Closed
解決したいこと
TauriでappWindow.listenを登録したいのですが、stateが更新されたタイミングで再レンダリングされるため、イベントが複数登録されてしまいます。
やっていること
テキストエディタアプリを作成しています。
コンポーネントがこちらのような階層になっています。
main.tsx
└ app.tsx ← ここでstateを登録している
├ textEditor.tsx ← テキストエディタを表示
└ tab.tsx ← 開いているファイルの一覧を表示
やりたいこととしては、テキストエディタにて値を編集したタイミングでstateを更新し、タブのファイル名表示に「*」をつけたいので、下記のようなコードを組んでいます。
export function App() {
const defaultValue = '';
const [inputValue, setInputValue] = useState('');
return (
<React.StrictMode>
<Tab
defaultValue={defaultValue}
inputValue={inputValue}
/>
<TextEditor
value={defaultValue}
setInputValue={setInputValue}
/>
</React.StrictMode>
);
}
他にも色々細かい部分が違ってはいるのですが、割愛しています。
このような感じで少なくとも問題なく動いていると思っていただけたら・・。
ただ、Tauriでアプリを作っているので、アプリケーションメニューバーを実装しOpenを押すと実際に開けるようにしました。
export function App() {
const [inputValue, setInputValue] = useState('');
appWindow.listen('open', () => {
const filePath = await dialog.open(dialogOption);
const text = await fs.readTextFile(filePath);
setInputValue(readFileText);
});
return (
<React.StrictMode>
<Tab
inputValue={inputValue}
/>
<TextEditor
setInputValue={setInputValue}
/>
</React.StrictMode>
);
}
ここからが問題でして、inputValue
が更新される度に再レンダリングされるため?なのかopenを押したときの処理がどんどん重なっていきます。
1回だけopenを押したのに、再レンダリングが重なった分だけダイアログが表示されてしまいます・・。
再レンダリングはfunction App()
を再度実行しているような形なのでしょうか?
また、これを回避するためにはどうしたら良いのでしょうか・・?
自分で試したこと
useStateより上の階層でappWindow.listenをしようとしたものの、setStateを呼び出したかったのでうまく出来ず・・。
useStateを使わずに子コンポーネントを任意のタイミングで再レンダリングする方法もないか調べてみたのですが、イマイチわかりませんでした。