React+Redux

actions.js

1
2
3
4
5
6
7
8
9
10
11
12
//action 创建函数
const action = (type, payload = {}) => ({ type, payload });

export const GET_ADS = 'GET_ADS';
export const ADD_ADS = 'ADD_ADS';
export const UPDATE_ADS = 'UPDATE_ADS';
export const DEL_ADS = 'DEL_ADS';

export const getAds = () => action(GET_ADS);
export const addAds = payload => action(ADD_ADS, payload);
export const updateAds = payload => action(UPDATE_ADS, payload);
export const delAds = payload => action(DEL_ADS, payload);

reducers.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { combineReducers } from 'redux';
import * as actionTypes from './actions';

export const adsResults = (state = [], action) => {
switch (action.type) {
case actionTypes.GET_ADS:
return [
...state,
action.payload
]

case actionTypes.ADD_ADS:
return [
...state,
action.payload.id
]

case actionTypes.DEL_ADS:
let newData = state.slice()
return newData.filter(item => item !== action.payload.id)

default:
return state
}
}

export const adsEntities = (state = {}, action) => {
switch (action.type) {
case actionTypes.GET_ADS:
return Object.assign(state, action.payload)

case actionTypes.ADD_ADS:
return Object.assign(state, {
[action.payload.id]: action.payload
})

case actionTypes.UPDATE_ADS:
// Why? 使用Object.assign()redu中的数据该表,但是界面不渲染
// return Object.assign(state, {
// [action.payload.id]: action.payload
// })
return {
...state,
[action.payload.id]: action.payload
}

default:
return state
}
}

const result = combineReducers({
ads: adsResults,
})

const entities = combineReducers({
ads: adsEntities,
})

export default combineReducers({
result,
entities,
})

export const combineData = (result, entities) => (result.map(item => entities[item]))

data.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export const ads = [
{
"id": 1,
"image": "http://api.handsomehan.cn:10013/media/20111009043132953_4NWLIlb.jpg",
"title": "月季花",
"description": null,
"page_view": 0
},
{
"id": 2,
"image": "http://api.handsomehan.cn:10013/media/tooopen_sy_121089197226_awrU7X6.jpg",
"title": "花",
"description": null,
"page_view": 0
}
]

store.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { normalize, schema } from 'normalizr';

import { ads } from '../data';

const data = {
ads: ads,
}

export const adSchema = new schema.Entity('ads');

export const stateSchema = {
ads: [adSchema],
}

export const initialState = normalize(data, stateSchema)

index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Ad from './Ad';
import registerServiceWorker from './registerServiceWorker';

import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducer from './reducers';

import { initialState } from './store';

export const store = createStore(
reducer,
initialState,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)

ReactDOM.render(
<Provider store={store}>
<Ad />
</Provider>
, document.getElementById('root'));
registerServiceWorker();

Ad.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';

import { getAds, addAds, delAds, updateAds } from './actions';
import { combineData } from './reducers';

class Ad extends Component {
AddAd = () => {
const payload = {
id: this.props.adsResult.length + 1,
title: '多肉植物',
description: '我会一朵🌺 ,可爱的🌺 。',
image: 'http://api.handsomehan.cn:10013/media/20111009043132953_4NWLIlb.jpg',
page_view: 0,
}

this.props.addAds(payload)
}

delAd = item => {
this.props.delAds(item)
}

updateAd = item => {
const payload = {
id: item.id,
title: '睡莲',
description: '我会一朵🌺 ,可爱的🌺 。',
image: 'http://api.handsomehan.cn:10013/media/20111009043132953_4NWLIlb.jpg',
page_view: 0,
}

this.props.updateAds(payload)
}

render() {
const { adsResult, adsEntities } = this.props
const ads = combineData(adsResult, adsEntities)

return (
<div>
{
ads.map(item => {
return (
<div key={item.id}>
<div>
{item.title}
{item.description}
</div>
<img style={{ height: 180, width: 300 }} src={item.image} alt={item.title} />
<button onClick={() => this.delAd(item)}>删除</button>
<button onClick={() => this.updateAd(item)}>更新</button>
</div>
)
})
}
<button onClick={this.AddAd}>添加广告</button>
</div>
);
}
}

const mapStateToProps = state => {
return {
adsResult: state.result.ads,
adsEntities: state.entities.ads,
}
}

const mapDispatchToProps = dispatch => {
return bindActionCreators({
getAds,
addAds,
delAds,
updateAds,
}, dispatch)
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(Ad)

package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "flower",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "1.0.17"
},
"dependencies": {
"normalizr": "^3.2.4",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}