-
Notifications
You must be signed in to change notification settings - Fork 0
DNET_ReactSecondStep2
nishi_74322014 edited this page Sep 11, 2026
·
1 revision
- 戻る(React -> Redux)
- ...Reactの5thステップ
- Reactのファースト・ステップ2
- Reactのセカンド・ステップ2
- Reactのサード・ステップ2
Redux対応を行う。
-
入力:プロンプト
以下で生成したコードを修正して3分割のヘッダ、左メニュー、メインエリアの画面のRedux対応を行うにはどのようにすればよいですか? npm create vite@latest my-app -- --template react-ts なお、「react-router-dom」が導入されており、左メニューのリンクを押下するとメインエリアが画面遷移するようになっている。 // src/App.tsx import { BrowserRouter, Routes, Route } from 'react-router-dom' import Header from './components/Header' import Sidebar from './components/Sidebar' import Home from './pages/Home' import About from './pages/About' import Settings from './pages/Settings' import { Counter } from './pages/Counter' import './App.css' function App() { return ( <BrowserRouter> <div className="app-container"> <Header /> <div className="body-container"> <Sidebar /> <main className="main-area"> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/settings" element={<Settings />} /> <Route path="/counter" element={<Counter />} /> </Routes> </main> </div> </div> </BrowserRouter> ) } export default App 追加ファイルの構成は以下の通り .\src\components\Header.tsx .\src\components\Sidebar.tsx .\src\pages\Home.tsx .\src\pages\About.tsx .\src\pages\Settings.tsx .\src\pages\Counter.tsx Redux対応の修正内容を教えてください。 -
出力:変更点のまとめ
- store/counterSlice.ts:CounterのState・Reducerを定義
- store/index.ts:Storeを構成、型をエクスポート
- main.tsx:
<Provider store={store}>でアプリ全体をラップ - pages/Counter.tsx:useState → useSelector/useDispatch に置き換え
Reduxのインストール
npm install @reduxjs/toolkit react-redux
-
src/store/counterSlice.ts(新規作成)
import { createSlice } from '@reduxjs/toolkit' import type { PayloadAction } from '@reduxjs/toolkit' interface CounterState { value: number } const initialState: CounterState = { value: 0, } const counterSlice = createSlice({ name: 'counter', initialState, reducers: { increment: (state) => { state.value += 1 }, decrement: (state) => { state.value -= 1 }, incrementByAmount: (state, action: PayloadAction<number>) => { state.value += action.payload }, reset: (state) => { state.value = 0 }, }, }) export const { increment, decrement, incrementByAmount, reset } = counterSlice.actions export default counterSlice.reducer
-
src/store/index.ts(新規作成)
import { configureStore } from '@reduxjs/toolkit' import counterReducer from './counterSlice' export const store = configureStore({ reducer: { counter: counterReducer, }, }) // 型エクスポート(useSelector / useDispatch で使用) export type RootState = ReturnType<typeof store.getState> export type AppDispatch = typeof store.dispatch
src/main.tsx(修正)
Provider で App 全体を囲みます。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Provider } from 'react-redux' // ← 追加
import { store } from './store' // ← 追加
import App from './App'
import './index.css'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<Provider store={store}> {/* ← 追加 */}
<App />
</Provider>
</StrictMode>,
)src/pages/Counter.tsx(修正)
- 以下は何回かエラーをプロンプトで修正している。
- 主に、既存コードを活かした修正方法に変更している。
import * as React from 'react';
// Redux 関連のインポート
import { useSelector, useDispatch } from 'react-redux';
import type { RootState, AppDispatch } from '../store';
import { increment, reset } from '../store/counterSlice';
// --- 既存コード
// Propsの型定義
type CounterProps //= {};
= {
currentCount: number;
onIncrement: () => void;
onReset: () => void;
};
// Stateの型定義
type CounterState = {
currentCount: number;
};
// 以下、Redux修正あり
// クラス名称を変更
export class Counter_org extends React.Component<CounterProps, CounterState> {
constructor(props: CounterProps) {
super(props);
this.state = { currentCount: 0 };
}
// Reduxのdispatchを呼び出す形に変更
render() {
return (
<div>
<h1>Counter</h1>
<p>This is a simple example of a React component.</p>
<p>Current count: <strong>{this.props.currentCount}</strong></p>
<button className='btn-primary' onClick={() => this.props.onIncrement()}>
Increment
</button>
<button className='btn-primary' onClick={() => this.props.onReset()}>
Reset
</button>
</div>
);
}
/*incrementCounter() {
this.setState({
currentCount: this.state.currentCount + 1,
});
}*/
}
// --- Reduxラッパー ---
export const Counter = () => {
const currentCount = useSelector((state: RootState) => state.counter.value);
const dispatch = useDispatch<AppDispatch>();
// dispatch の戻り値を void に吸収させる
const handleIncrement = (): void => { dispatch(increment()); };
const handleReset = (): void => { dispatch(reset()); };
return (
<Counter_org
currentCount={currentCount}
onIncrement={handleIncrement}
onReset={handleReset}
/>
);
};-
入力:プロンプト
Redux対応の効果を観測するためにsrc\pages\Counter.tsxのcount情報をsrc\pages\About.tsxでも使用したい。どの様に変更しますか?以下は前提となる現実装の情報です。 * src\main.tsx ```typescriptreact import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import './index.css' import App from './App.tsx' // Redux 関連のインポート import { Provider } from 'react-redux' import { store } from './store' createRoot(document.getElementById('root')!).render( <StrictMode> <Provider store={store}> <App /> </Provider> </StrictMode>, ) ``` * src\store\index.ts ```typescript import { configureStore } from '@reduxjs/toolkit' import counterReducer from './counterSlice' export const store = configureStore({ reducer: { counter: counterReducer, }, }) // 型エクスポート(useSelector / useDispatch で使用) export type RootState = ReturnType<typeof store.getState> export type AppDispatch = typeof store.dispatch ``` * src\store\counterSlice.ts ```typescript import { createSlice } from '@reduxjs/toolkit' import type { PayloadAction } from '@reduxjs/toolkit' interface CounterState { value: number } const initialState: CounterState = { value: 0, } const counterSlice = createSlice({ name: 'counter', initialState, reducers: { increment: (state) => { state.value += 1 }, decrement: (state) => { state.value -= 1 }, incrementByAmount: (state, action: PayloadAction<number>) => { state.value += action.payload }, reset: (state) => { state.value = 0 }, }, }) export const { increment, decrement, incrementByAmount, reset } = counterSlice.actions export default counterSlice.reducer ``` -
出力:変更点のまとめ
ReduxのstoreはすでにProviderでアプリ全体に提供されているので、
About.tsxにuseSelectorを追加するだけでcount情報を取得できる。
「修正内容1」で変更済み。
src/pages/About.tsx(修正)
// 追加するインポート
import { useSelector } from 'react-redux'
import type { RootState } from '../store'
export default function About() {
// Reduxのstoreからcount値を取得
const count = useSelector((state: RootState) => state.counter.value)
return (
<div>
<h1>About</h1>
{/* count情報を表示 */}
<p>現在のカウント: {count}</p>
</div>
)
}- FrontendTemplates/UI/SPA/React at develop · OpenTouryoProject/FrontendTemplates
https://github.com/OpenTouryoProject/FrontendTemplates/tree/develop/UI/SPA/React
移行メモ
- プロンプト中の「追加フィアルの構成」→「追加ファイルの構成」に修正した。
- 生成AIの出力をそのまま貼り付けたことによりコードの先頭に コード・ブロックの言語名が混入していた箇所(
tsximport { StrictMode } ...、tsx// 追加するインポート)は、言語名を除去してコード・フェンスの 言語指定に移した。- 「Provider で App 全体を囲みます。」は元 Wiki では整形済みテキスト (コード)の一部になっていたが、説明文であるため本文に戻した。
- PukiWiki のページ内アンカ(
#xxxxxxxx)は GitHub Wiki では再現できないため、 同一ページ内のアンカは見出しから生成されるアンカに張り替えた。
Tags: 移行, React, Redux, セカンド・ステップ, Redux Toolkit, useSelector, useDispatch, Vite
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。