(一)react-redux useSelector 学习样例 + 详细解析
npx create-react-app my-project --template typescript
cd my-project
安装依赖
npm install redux react-redux immer antd
npm install @types/react @types/react-dom @types/react-redux --save-dev
npm install ajv@^8.0.0
项目结构:
package.json
{
"name": "my-project",
"version": "0.1.0",
"private": true,
"dependencies": {
"@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.19",
"ajv": "^8.17.1",
"antd": "^5.22.2",
"immer": "^10.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^8.0.5",
"react-scripts": "5.0.1",
"redux": "^4.2.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"
]
},
"devDependencies": {
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"@types/react-redux": "^7.1.23"
}
}
- public/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>redux</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
- src/redux/actions/index.ts
export const SET_GIFT_ITEMS = 'SET_GIFT_ITEMS';
export const setGiftItems = (giftItems: any[]) => ({
type: SET_GIFT_ITEMS,
payload: giftItems,
});
- src/redux/reducers/index.ts
import { combineReducers } from 'redux';
import { SET_GIFT_ITEMS } from '../actions';
const initialSettingInfo = {
giftOptionIndex: 0,
giftItems: [],
};
const settingInfo = (state = initialSettingInfo, action: { type: any; payload: any; }) => {
switch (action.type) {
case SET_GIFT_ITEMS:
return {
...state,
giftItems: action.payload,
};
default:
return state;
}
};
const rootReducer = combineReducers({
settingInfo,
});
export default rootReducer;
- src/store/index.ts
import { createStore } from 'redux';
import rootReducer from '../reducers';
const store = createStore(rootReducer);
export default store;
- src/components
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Select, Button } from 'antd';
import { setGiftItems } from '../redux/actions';
const { Option } = Select;
const giftList = [
{ giftId: 1, giftName: '礼物1' },
{ giftId: 2, giftName: '礼物2' },
{ giftId: 3, giftName: '礼物3' },
];
const GiftSelector = () => {
const [selectedGiftId, setSelectedGiftId] = useState(null);
const dispatch = useDispatch();
// @ts-ignore
const giftItems = useSelector((state) => state.settingInfo.giftItems);
const handleChange = (value: React.SetStateAction<null>) => {
setSelectedGiftId(value);
};
const handleAddGift = () => {
if (selectedGiftId) {
const selectedGift = giftList.find((gift) => gift.giftId === selectedGiftId);
const newGiftItems = [...giftItems, selectedGift];
dispatch(setGiftItems(newGiftItems));
}
};
return (
<div>
<Select style={{ width: 200 }} onChange={handleChange} placeholder="选择一个礼物">
{giftList.map((gift) => (
<Option key={gift.giftId} value={gift.giftId}>
{gift.giftName}
</Option>
))}
</Select>
<Button type="primary" onClick={handleAddGift} style={{ marginLeft: 10 }}>
添加
</Button>
<div>
<h3>已添加的礼物:</h3>
{giftItems.map((gift: { giftId: number; giftName: string }) => (
<div key={gift.giftId}>{gift.giftName}</div>
))}
</div>
</div>
);
};
export default GiftSelector;
- App.tsx
import React from 'react';
import { Provider } from 'react-redux';
import store from './redux/store';
import GiftSelector from './components/GiftSelector';
// import 'antd/dist/antd.css';
const App = () => {
return (
<Provider store={store}>
<GiftSelector />
</Provider>
);
};
export default App;
- index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);