├── public
├── favicon.ico
├── screenshot.png
└── index.html
├── src
├── reducers
│ ├── index.js
│ └── goods.js
├── stores
│ ├── initState.js
│ └── configStore.js
├── index.css
├── components
│ ├── goods
│ │ ├── Content.jsx
│ │ ├── GoodList.jsx
│ │ ├── Add.jsx
│ │ ├── CategoryFilter.css
│ │ ├── Good.jsx
│ │ ├── CategoryFilter.jsx
│ │ ├── Add.css
│ │ └── GoodList.css
│ └── common
│ │ ├── header
│ │ ├── Header.jsx
│ │ └── Header.css
│ │ └── footer
│ │ ├── Footer.css
│ │ └── Footer.jsx
├── utils
│ └── createReducer.js
├── index.js
├── containers
│ ├── App.css
│ ├── App.jsx
│ └── GoodContent.js
├── service
│ └── goodService.js
└── actions
│ └── goods.js
├── .gitignore
├── README.md
├── package.json
└── LICENSE
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/react-ponitor/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/giscafer/react-ponitor/HEAD/public/screenshot.png
--------------------------------------------------------------------------------
/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 | import goods from './goods'
3 |
4 | export default combineReducers({
5 | goods
6 | })
--------------------------------------------------------------------------------
/src/stores/initState.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * 整个应用的STATE TREE 及初始值
4 | */
5 | export default {
6 | good:{
7 | goods:[],
8 | goodType:''
9 | }
10 | }
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: Source Sans Pro,Helvetica Neue,Arial,sans-serif;
5 | }
6 |
7 | @media screen and (max-width:479px){
8 | img.fork{
9 | width:80px;
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/src/reducers/goods.js:
--------------------------------------------------------------------------------
1 |
2 | import createReducer from '../utils/createReducer'
3 | import { ACTION_HANDLERS } from '../actions/goods'
4 | import initState from '../stores/initState'
5 |
6 | export default createReducer(initState.good, ACTION_HANDLERS)
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # testing
7 | coverage
8 |
9 | # production
10 | build
11 |
12 | # misc
13 | .DS_Store
14 | .env
15 | npm-debug.log
16 |
--------------------------------------------------------------------------------
/src/components/goods/Content.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 商品分类过来
3 | */
4 | import React from 'react'
5 | import CategoryFilter from './CategoryFilter'
6 | export default ()=>{
7 | return (
8 |
9 |
10 |
11 | )
12 | }
--------------------------------------------------------------------------------
/src/utils/createReducer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 统一生成reducer
3 | */
4 | export default function createReducer(initState, handlers) {
5 | return function reducer(state = initState, action) {
6 | const handler = handlers[action.type]
7 | return handler ? handler(state, action) : state
8 | }
9 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Provider } from 'react-redux';
3 | import ReactDOM from 'react-dom';
4 | import App from './containers/App';
5 | import store from './stores/configStore'
6 | import './index.css';
7 |
8 | ReactDOM.render(
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 |
--------------------------------------------------------------------------------
/src/components/goods/GoodList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Good from './Good'
3 | import './GoodList.css'
4 | export default ({goods=[]})=>{
5 | return (
6 |
7 | {
8 | goods.map((good,index)=>{
9 | return
10 | })
11 | }
12 |
13 | )
14 | }
--------------------------------------------------------------------------------
/src/stores/configStore.js:
--------------------------------------------------------------------------------
1 | import { applyMiddleware, createStore, compose } from 'redux';
2 | import createLogger from 'redux-logger';
3 | import thunk from 'redux-thunk';
4 | import reducer from '../reducers/index'
5 |
6 |
7 | let enhancer = compose(
8 | applyMiddleware(thunk, createLogger()),
9 | // applyMiddleware(thunk),
10 | window.devToolsExtension ? window.devToolsExtension() : f => f
11 | );
12 |
13 | export default createStore(reducer, enhancer)
--------------------------------------------------------------------------------
/src/containers/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | animation: App-logo-spin infinite 20s linear;
7 | height: 80px;
8 | }
9 |
10 | .App-header {
11 | background: linear-gradient(90deg,#1192b9 10%,#a0d7f6 90%);
12 | height: 150px;
13 | padding: 20px;
14 | color: white;
15 | }
16 |
17 | .App-nav {
18 | font-size: large;
19 | margin-top:1em
20 | }
21 |
22 | @keyframes App-logo-spin {
23 | from { transform: rotate(0deg); }
24 | to { transform: rotate(360deg); }
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/common/header/Header.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './Header.css'
3 | export default ()=>{
4 | return (
5 |
13 | )
14 | }
--------------------------------------------------------------------------------
/src/containers/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | // import logo from './logo.svg';
3 | import './App.css';
4 | import Header from '../components/common/header/Header';
5 | import Footer from '../components/common/footer/Footer';
6 | import GoodContent from './GoodContent';
7 |
8 | class App extends Component {
9 | render() {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 | )
17 | }
18 | }
19 |
20 | export default App;
21 |
--------------------------------------------------------------------------------
/src/components/goods/Add.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 商品链接输入框UI组件
3 | */
4 | import React from 'react'
5 | import './Add.css'
6 | export default ({onAddClickHandler}) => {
7 | return (
8 |
9 |
10 |
关注价格,在最适合的时候购买
11 | { window.textInput = input; } } />
12 |
13 |
14 |
15 | )
16 | }
--------------------------------------------------------------------------------
/src/components/goods/CategoryFilter.css:
--------------------------------------------------------------------------------
1 | .cate{
2 | display: block;
3 | margin-top:10px
4 | }
5 | .cate nav{
6 | display: inline-flex;;
7 | display: -webkit-inline-flex;; /* Safari Chrome*/
8 | display: -moz-inline-flex;; /* Firefox */
9 | justify-content:center;
10 | }
11 | .cate nav > span{
12 | cursor: pointer;
13 | border-radius: 13px;
14 | margin: 0 1em 0 1em ;
15 | padding: 5px 10px
16 | }
17 | .cate nav > span.selected{
18 | background-color: #1192b9;
19 | color: #fff
20 | }
21 | .cate nav > span:hover{
22 | background-color: #ccc;
23 | margin: 0 1em 0 1em;
24 | color:#1192b9
25 | }
26 |
27 | @media screen and (max-width:479px){
28 |
29 | .cate nav > span{
30 | margin: 0 1em 0 1em ;
31 | padding: 2px 5px
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/src/components/common/footer/Footer.css:
--------------------------------------------------------------------------------
1 | footer{
2 | font-size: 14px;
3 | position: fixed;
4 | bottom: 0;
5 | width: 100%;
6 | text-align: center;
7 | }
8 | .footer::before{
9 | display: table;
10 | content: " ";
11 | }
12 | .footer::after{
13 | clear: both;
14 | display: table;
15 | content: " ";
16 | }
17 | .footer ul{
18 | display: inline-flex;;
19 | display: -webkit-inline-flex;; /* Safari Chrome*/
20 | display: -moz-inline-flex;; /* Firefox */
21 | list-style: none;
22 | justify-content: center
23 | }
24 | .footer li{
25 | margin: 0 0.5em 0 0.5em;
26 | color:#777
27 | }
28 | .footer li>a{
29 | color:#333;
30 | text-decoration: underline
31 | }
32 |
33 | @media screen and (max-width: 479px) {
34 | .footer ul>li.phone{
35 | display:none
36 | }
37 | }
--------------------------------------------------------------------------------
/src/components/goods/Good.jsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react'
3 |
4 | export default ({goodInfo = {}}) => {
5 | let name=window.innerWidth>479?goodInfo.name:goodInfo.name.substring(0,8)
6 | return (
7 |
8 |
9 |

10 |
11 | {name}
12 |
{goodInfo.priceText}
13 |
详情
14 | { /*
趋势*/}
15 |
16 |
17 |
18 | )
19 | }
--------------------------------------------------------------------------------
/src/components/common/footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './Footer.css'
3 | export default () => {
4 | return (
5 |
14 | )
15 | }
--------------------------------------------------------------------------------
/src/components/common/header/Header.css:
--------------------------------------------------------------------------------
1 | header {
2 | background: white;
3 | height: 50px;
4 | margin-bottom: 0;
5 | }
6 |
7 | .nav {
8 | list-style: none;
9 | text-decoration: none;
10 | margin-left:6em;
11 | }
12 |
13 | @media screen and (max-width: 479px) {
14 | .nav {
15 | margin-left:-1.5em;
16 | }
17 | }
18 |
19 | #navbar {
20 | margin-bottom: 0
21 | }
22 |
23 | #logo {
24 | font-size: 1.5em;
25 | color: #1192b9
26 | }
27 | @media screen and (max-width: 479px) {
28 | #logo {
29 | font-size: 1.2em;
30 | color: #1d976c
31 | }
32 | }
33 |
34 | #forgot_password {
35 | float: left
36 | }
37 |
38 | #nv-menu {
39 | margin-right: 50px;
40 | margin-top: 9px
41 | }
42 |
43 | a {
44 | text-decoration: none;
45 | }
46 |
47 | .navbar-header {
48 | float: left;
49 | }
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-ponitor
2 |
3 | [ P ] rice + M [ onitor ] = Ponitor 价格监测
4 |
5 | 可添加天猫、淘宝、京东、Apple App的商品,监控商品价格发生变动时(每天定时器),推送消息。
6 |
7 | 服务端请求 [Ponitor](https://github.com/giscafer/Ponitor/) 应用测试demo
8 |
9 | [Ponitor](https://github.com/giscafer/Ponitor/) 是早期vue.js 1.x开发,**react-ponitor** 是使用 react + react-redux 改写其前端部分
10 |
11 | 本demo演示地址:https://giscafer.github.io/react-ponitor/
12 |
13 |
14 |
15 | ## Sreenshot
16 |
17 | 
18 |
19 | ## Usage
20 |
21 | ```
22 | npm install
23 | ```
24 |
25 | ```
26 | npm run start
27 | ```
28 |
29 | ## License
30 |
31 | MIT
32 |
33 | > Blog [giscafer.com](http://giscafer.com) ·
34 | > GitHub [@giscafer](https://github.com/giscafer) ·
35 | > Weibo [@Nickbing Lao](https://weibo.com/laohoubin)
36 |
--------------------------------------------------------------------------------
/src/components/goods/CategoryFilter.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * 商品分类过来
3 | */
4 | import React from 'react'
5 | import './CategoryFilter.css'
6 |
7 | export default ({onFilterClick, filterType}) => {
8 | console.log(filterType)
9 | return (
10 |
11 |
17 |
18 | )
19 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-ponitor",
3 | "version": "0.1.0",
4 | "private": false,
5 | "description": "商品价格监测应用",
6 | "keywords": [
7 | "react",
8 | "ponitor",
9 | "react-redux"
10 | ],
11 | "author": "Nickbing Lao ",
12 | "devDependencies": {
13 | "autoprefixer": "^6.6.1",
14 | "react-scripts": "0.8.5"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/kenberkeley/react-demo.git"
19 | },
20 | "dependencies": {
21 | "es6-promise": "^4.0.5",
22 | "react": "^15.4.2",
23 | "react-dom": "^15.4.2",
24 | "react-redux": "^5.0.2",
25 | "redux": "^3.6.0",
26 | "redux-logger": "^2.7.4",
27 | "redux-thunk": "^2.2.0",
28 | "superagent": "^3.3.2"
29 | },
30 | "scripts": {
31 | "start": "react-scripts start",
32 | "build": "react-scripts build",
33 | "test": "react-scripts test --env=jsdom",
34 | "eject": "react-scripts eject"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Nickbing Lao
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/containers/GoodContent.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { bindActionCreators } from 'redux'
3 | import { connect } from 'react-redux'
4 | import Add from '../components/goods/Add'
5 | import GoodList from '../components/goods/GoodList'
6 | import CategoryFilter from '../components/goods/CategoryFilter'
7 | import goodAction from '../actions/goods'
8 |
9 |
10 | class GoodContent extends Component {
11 | /* constructor(){
12 | super();
13 | }*/
14 | componentWillMount() {
15 | const {queryList} = this.props
16 | queryList('all')
17 | }
18 |
19 | render() {
20 | let {good, queryList, addGood} = this.props;
21 | // console.log(good)
22 | return (
23 |
28 | )
29 | }
30 | }
31 |
32 |
33 | function mapStateToProps(state) {
34 | // console.log(state)
35 | return {
36 | good: state.goods
37 | }
38 | }
39 |
40 | function mapDispatchToProps(dispatch) {
41 | return bindActionCreators(goodAction, dispatch)
42 | }
43 |
44 | export default connect(mapStateToProps, mapDispatchToProps)(GoodContent)
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/components/goods/Add.css:
--------------------------------------------------------------------------------
1 |
2 | #add-good {
3 | text-align: center;
4 | margin-top: 1em
5 | }
6 | #add-good button {
7 | cursor: pointer;
8 | border: 1px solid #d5d5d5;
9 | padding-left: 1em;
10 | text-decoration: none;
11 | border-radius: 0 2em 2em 0;
12 | line-height:2em;
13 | padding-right: 1em
14 | }
15 | #add-good h4 {
16 | margin-left: 5px;
17 | font-size: 1.5em;
18 | font-weight: normal;
19 | color: #fff;
20 | margin-bottom:10px
21 | }
22 | #add-good input{
23 | width: 45em;
24 | height: 2em;
25 | border: 1px solid #d5d5d5;
26 | border-right: none;
27 | border-radius: 2em 0 0 2em;
28 | padding: .2em 1em .2em;
29 | outline: none
30 | }
31 |
32 |
33 | .input-group-btn {
34 | position: relative;
35 | font-size: 0;
36 | white-space: nowrap
37 | }
38 |
39 | .input-group-btn>.btn {
40 | position: relative;
41 | height: 2.5em
42 | }
43 |
44 | @media screen and (max-width:479px){
45 | #add-good input{
46 | width: 60%;
47 | height: 1.4em;
48 | border: 1px solid #d5d5d5;
49 | border-right: none;
50 | border-radius: 1em 0 0 1em;
51 | padding: .2em 2em .2em;
52 | margin-left:1em;
53 | outline: none
54 | }
55 | #add-good button {
56 | border: 1px solid #d5d5d5;
57 | padding-left: 1em;
58 | text-decoration: none;
59 | border-radius: 0 2em 2em 0;
60 | line-height:1em;
61 | padding-right: 1em
62 | }
63 |
64 | .input-group-btn>.btn {
65 | position: relative;
66 | height: 2em
67 | }
68 | #add-good h4 {
69 | font-size: 1.2em;
70 | }
71 | }
--------------------------------------------------------------------------------
/src/service/goodService.js:
--------------------------------------------------------------------------------
1 |
2 | require('es6-promise').polyfill();
3 | import request from 'superagent';
4 | const SERVER_URL = 'http://project.xinong.wang:18080';
5 | //测试用户giscafer的ID,如果需要服务器,建议看项目的后端部分https://github.com/giscafer/Ponitor/,自行注册用户,复制userId
6 | const USER_ID = '5739a47c35827d2c06b5dd01';
7 | class GoodService {
8 |
9 | query(type = '', cb) {
10 | if (!cb) throw new Error("Bad response from server");
11 | request
12 | .post(`${SERVER_URL}/api/good/${type}/${USER_ID}`)
13 | .end((err, res) => {
14 | if (err) {
15 | return alert(err)
16 | }
17 | if (res.body.result_code === -1) {
18 | return alert(res.body.error);
19 | }
20 | cb(res.body['data']);
21 | });
22 | }
23 |
24 | add(url = null, cb) {
25 | if(!url){
26 |
27 | }
28 | if (!cb) throw new Error("Bad response from server");
29 |
30 | let bodyParams = {
31 | 'userId': USER_ID,
32 | 'url': url
33 | }
34 | request
35 | .post(`${SERVER_URL}/api/good`)
36 | .send(bodyParams)
37 | .end((err, res) => {
38 | if (err) {
39 | return alert(err)
40 | }
41 | if (res.body.result_code === -1 || res.body.error) {
42 | return alert(res.body.error);
43 | }else if(res.body.errors){
44 | return alert(res.body.message || res.body.errors);
45 | }
46 | cb(res.body);
47 | });
48 | }
49 | }
50 |
51 | export default new GoodService();
52 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 | React-Ponitor 价格监控
17 |
18 |
19 |
20 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/components/goods/GoodList.css:
--------------------------------------------------------------------------------
1 |
2 | .good-column{
3 | display: -webkit-flex; /* Safari */
4 | display: -moz-flex;
5 | display: flex;
6 | -webkit-justify-content:flex-start;
7 | -moz-justify-content:flex-start;
8 | justify-content:flex-start;
9 | /* flex-direction:column;
10 | -webkit-flex-direction:column;
11 | -moz-flex-direction:column;*/
12 | margin:2em 6em 6em 6em;
13 | flex-wrap:wrap;
14 | -webkit-flex-wrap:wrap;
15 | -moz-flex-wrap:wrap;
16 | }
17 | .good-column .good{
18 | width: 9em;
19 | padding: 2em 1.5em;
20 | }
21 |
22 | .good-column .good:hover{
23 | background-color: #eee
24 | }
25 |
26 | .good-column .good .good-price{
27 | margin:4px;
28 | background-color:#eee;
29 | color:red;
30 | border-radius: 8px
31 | }
32 | .good-column .good .good-name a.detail{
33 | background-color:#eee;
34 | padding: 3px 8px;
35 | border-radius: 3px;
36 | }
37 | .good-column .good .good-name a.detail:hover{
38 | background-color:green;
39 | color: #fff
40 | }
41 | .good-column .good .icon img{
42 | width: 9em;
43 | height:9em;
44 | border-radius: 2em;
45 | }
46 |
47 | @media screen and (max-width:479px){
48 | .good-column{
49 | -webkit-justify-content:space-around;
50 | -moz-justify-content:space-around;
51 | justify-content:space-around;
52 | margin:1em 0.53em 2em 0.3em;
53 |
54 | }
55 | .good-column .good{
56 | width: 4em;
57 | padding: 1em 1em;
58 | }
59 | .good-column .good .icon img{
60 | width: 4em;
61 | height:4em;
62 | border-radius: 1em;
63 | }
64 | .good-column .good .good-price{
65 | margin:4px;
66 | font-size: 0.9em;
67 | background-color:#eee;
68 | color:red;
69 | border-radius: 8px
70 | }
71 | }
--------------------------------------------------------------------------------
/src/actions/goods.js:
--------------------------------------------------------------------------------
1 |
2 | import goodService from '../service/goodService'
3 |
4 | // Action Type
5 | const FETCH_GOOD = 'FETCH_GOOD'
6 | const ADD_GOOD = 'ADD_GOOD'
7 | // const DEL_GOOD = 'DEL_GOOD'//
8 |
9 | // Action Creator
10 |
11 | //父类过滤
12 | const filterGood = (goods, type = 'all') => {
13 | if (type !== 'all') {
14 | goods = goods.filter(good => {
15 | return good.type === type
16 | });
17 | }
18 | return { goods, goodType: type };
19 | }
20 | const fetchGood = (type, dispatch) => {
21 | goodService.query(type, (goods) => {
22 | sessionStorage.goods = JSON.stringify(goods);
23 | dispatch({
24 | type: FETCH_GOOD,
25 | payload: filterGood(goods, type)
26 | })
27 | })
28 | }
29 | // 设计一次查询所有商品时,前端sessionStorage保存,查询其他类别不走请求
30 | const queryList = type => dispatch => {
31 | if (type === 'all') {
32 | fetchGood(type, dispatch)
33 | } else {
34 | let goods = sessionStorage.goods && JSON.parse(sessionStorage.goods);
35 | if (goods && goods.length) {
36 | dispatch({
37 | type: FETCH_GOOD,
38 | payload: filterGood(goods, type)
39 | })
40 | }
41 | }
42 | }
43 |
44 | const addGood = url => dispatch => {
45 | goodService.add(url, good => {
46 | dispatch({
47 | type: ADD_GOOD,
48 | payload: good
49 | })
50 | });
51 | }
52 |
53 |
54 | export default {
55 | queryList, addGood
56 | }
57 |
58 | // 参考网友的写法
59 | // ================================
60 | // Action handlers for Reducer
61 | // 本来更新 state 是 Reducer 的责任
62 | // 但要把 ActionType 导出又引入实在太麻烦
63 | // 且在 Reducer 中写 switch-case 实在太不优雅
64 | // 故在此直接给出处理逻辑
65 | // ================================
66 | export const ACTION_HANDLERS = {
67 | [FETCH_GOOD]: (good, {payload}) => payload,
68 | [ADD_GOOD]: (state, {payload}) => {
69 | let goods = sessionStorage.goods && JSON.parse(sessionStorage.goods);
70 | console.log(state)
71 | let temp = [...goods, payload];
72 | return filterGood(temp,payload.type);
73 | }
74 | }
--------------------------------------------------------------------------------