npx create-react-app my-redux-app --template typescript
cd my-redux-app
npm install @reduxjs/toolkit react-reduxnpm install ajv@^8.0.0
npm install antd
- package.json
{"name": "my-redux-app","version": "0.1.0","private": true,"dependencies": {"@reduxjs/toolkit": "^2.3.0","@testing-library/jest-dom": "^5.17.0","@testing-library/react": "^13.4.0","@testing-library/user-event": "^13.5.0","@types/jest": "^27.5.2","@types/node": "^16.18.120","@types/react": "^18.3.12","@types/react-dom": "^18.3.1","ajv": "^8.17.1","antd": "^5.22.2","react": "^18.3.1","react-dom": "^18.3.1","react-redux": "^9.1.2","react-scripts": "5.0.1","typescript": "^4.9.5","web-vitals": "^2.1.4"},"scripts": {"start": "react-scripts start","build": "react-scripts build","test": "react-scripts test","eject": "react-scripts eject"},"eslintConfig": {"extends": ["react-app","react-app/jest"]},"browserslist": {"production": [">0.2%","not dead","not op_mini all"],"development": ["last 1 chrome version","last 1 firefox version","last 1 safari version"]}
}
项目结构:
- src/store/counter.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'// 这是一个简单的redux使用示例,可以参考export interface CounterState {value: number;status: 'idle' | 'loading' | 'failed';list: Array<string>;
}const initialState: CounterState = {value: 0,status: 'idle',list: [],
};export const counterSlice = createSlice({name: 'counter',initialState,reducers: {increment: (state: CounterState) => {// Redux Toolkit allows us to write "mutating" logic in reducers. It// doesn't actually mutate the state because it uses the Immer library,// which detects changes to a "draft state" and produces a brand new// immutable state based off those changesstate.value += 1;state.list.push(`${state.value}`);},decrement: (state: CounterState) => {state.value -= 1;state.list.pop();},incrementByAmount: (state: CounterState, action: PayloadAction<number>) => {state.value += action.payloadstate.list.push(`${state.value}`);},},
})// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actionsexport default counterSlice.reducer
- src/store/store.ts
import { configureStore } from '@reduxjs/toolkit';
import counterSlice from "./counter";
export const store = configureStore({reducer: {counter: counterSlice,},middleware: (getDefaultMiddleware) =>getDefaultMiddleware({serializableCheck: false,}),
});// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;// 监听store的变化
store.subscribe(() => {// const state = store.getState() as RootState;// console.log(state);
});
- App.tsx
// src/App.tsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from './store/store';
import { increment, decrement, incrementByAmount } from './store/counter';
import {Button} from 'antd';
const App: React.FC = () => {const count = useSelector((state: RootState) => state.counter.value);const dispatch = useDispatch();return (<div style={{ textAlign: 'center', marginTop: '20px' }}><h1>计数器: {count}</h1><Button onClick={() => dispatch(increment())}>增加</Button> <Button onClick={() => dispatch(decrement())}>减少</Button> <Button onClick={() => dispatch(incrementByAmount(5))}>增加5</Button></div>);
};export default App;
- index.tsx
// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './store/store';
import App from './App';const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement
);
root.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>
);