やっていること
RustのGUIフレームワーク、Tauriを使用してGUIを書いています。
ReactとReduxを使い、GUI(タブ分割)を実現したいと思っています。
やりたいこと
ボタンをクリックしたらRust側でカウントを1増やす。
UI側でタブを別タブに切り替える
戻したときにUIのステートが切り替える前と同じ状態に戻っていること
コード
rust
1#![cfg_attr( 2 all(not(debug_assertions), target_os = "windows"), 3 windows_subsystem = "windows" 4)] 5 6fn main() { 7 let context = tauri::generate_context!(); 8 tauri::Builder::default() 9 .invoke_handler(tauri::generate_handler![countup,]) 10 .menu(tauri::Menu::os_default(&context.package_info().name)) 11 .run(context) 12 .expect("error while running tauri application"); 13} 14 15#[tauri::command] 16fn countup(count: i32) -> i32 { 17 println!("{}", count + 1); 18 count + 1 19}
UI側
package.json
1{ 2 "name": "tauri-app", 3 "version": "0.1.0", 4 "private": true, 5 "dependencies": { 6 "@reduxjs/toolkit": "^1.8.2", 7 "@tauri-apps/api": "^1.0.1", 8 "@testing-library/jest-dom": "^5.16.4", 9 "@testing-library/react": "^13.3.0", 10 "@testing-library/user-event": "^13.5.0", 11 "@types/jest": "^27.5.2", 12 "@types/node": "^16.11.41", 13 "@types/react": "^18.0.14", 14 "@types/react-dom": "^18.0.5", 15 "@types/react-redux": "^7.1.24", 16 "react": "^18.2.0", 17 "react-dom": "^18.2.0", 18 "react-redux": "file:types/react-redux@reduxjs/toolkit", 19 "react-scripts": "^5.0.1", 20 "react-tabs": "^5.1.0", 21 "typescript": "^4.7.4", 22 "web-vitals": "^2.1.4" 23 }, 24 "scripts": { 25 "start": "cross-env BROWSER=none react-scripts start", 26 "build": "react-scripts build", 27 "test": "react-scripts test", 28 "eject": "react-scripts eject", 29 "tauri": "tauri" 30 }, 31 "eslintConfig": { 32 "extends": [ 33 "react-app", 34 "react-app/jest" 35 ] 36 }, 37 "browserslist": { 38 "production": [ 39 ">0.2%", 40 "not dead", 41 "not op_mini all" 42 ], 43 "development": [ 44 "last 1 chrome version", 45 "last 1 firefox version", 46 "last 1 safari version" 47 ] 48 }, 49 "devDependencies": { 50 "@tauri-apps/cli": "^1.0.0", 51 "cross-env": "^7.0.3" 52 } 53}
App.tsx
1import React from 'react'; 2import './App.css'; 3import './tab_style.css' 4// import 'react-tabs/style/react-tabs.css'; 5import { invoke } from '@tauri-apps/api'; 6import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'; 7import { TabPage1 } from './TabPages/TabPage1' 8 9class App extends React.Component { 10 render(): React.ReactNode { 11 return ( 12 <div className="App"> 13 <TabUI></TabUI> 14 </div> 15 ); 16 } 17} 18 19class TabUI extends React.Component { 20 state = { 21 value: 0, 22 }; 23 24 handleChange = (value: any) => { 25 this.setState({ value }); 26 console.log(value) 27 }; 28 render() { 29 const { value } = this.state; 30 return (<div id="react_tab_conainer"> 31 <Tabs 32 value={value} onChange={this.handleChange}> 33 <TabList> 34 <Tab>Counter</Tab> 35 <Tab>Bar</Tab> 36 <Tab>Baz</Tab> 37 </TabList> 38 <TabPanel> 39 <TabPage1></TabPage1> 40 </TabPanel> 41 <TabPanel> 42 {Page2()} 43 </TabPanel> 44 <TabPanel> 45 Baz 46 </TabPanel> 47 </Tabs> 48 </div > 49 ) 50 } 51} 52 53 54function Page2() { 55 return (<div className="panel-content"></div>) 56} 57 58export default App;
store.tsx
1import { configureStore, createSlice } from '@reduxjs/toolkit' 2import { TabPage1, TabPage1Slice } from './TabPages/TabPage1' 3 4const store = configureStore({ 5 reducer: TabPage1Slice.reducer 6});
import React from 'react'; import './../App.css'; import './../tab_style.css' // import 'react-tabs/style/react-tabs.css'; import { invoke } from '@tauri-apps/api'; import { configureStore, createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' import { useSelector, useDispatch } from 'react-redux'; // 非同期 const clickAsync = createAsyncThunk( "rust/count", async (count: number) => { return await invoke("countup", { count: count }); } ); export const TabPage1Slice = createSlice({ name: 'TabPage1Slice', initialState: { counter: 0 }, reducers: {}, extraReducers: (builder) => { builder.addCase(clickAsync.fulfilled, (state, action: PayloadAction<any>) => { state.counter = action.payload; }); } }); export class TabPage1 extends React.Component<{}, { counter: number }>{ constructor(props: any) { super(props) this.state = { counter: 0 } } render(): React.ReactNode { const dispatch = useDispatch(); return (<Counter handleClick={() => { dispatch(clickAsync(this.state.counter)) }} counter={this.state.counter} > </Counter>) } } function Counter(props: any) { return ( <div className="panel-content" > <button onClick={props.handleClick}> Click</button> <label> {props.counter} </label> </div> ) }
発生しているエラー
ERROR [eslint] src\TabPages\TabPage1.tsx Line 40:26: React Hook "useDispatch" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks Search for the keywords to learn more about each error. ERROR [eslint] src\TabPages\TabPage1.tsx Line 40:26: React Hook "useDispatch" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks Search for the keywords to learn more about each error. ERROR in src/TabPages/TabPage1.tsx:41:56 TS2345: Argument of type 'AsyncThunkAction<RejectWithValue<unknown, unknown>, number, {}>' is not assignable to parameter of type 'AnyAction'. 39 | render(): React.ReactNode { 40 | const dispatch = useDispatch(); > 41 | return (<Counter handleClick={() => { dispatch(clickAsync(this.state.counter)) }} counter={this.state.counter} > </Counter>) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 42 | } 43 | } 44 |
TypeScriptとReactが分からなさすぎてエラーを読んでも理解が出来ません。
具体的に何をどうしたらいいのでしょうか?
すごくふわっとしていて申し訳ないんですが、宜しくお願いします。

回答1件
あなたの回答
tips
プレビュー