每当此项目选择添加到购物车时,我都会尝试保存用户的项目选择。每当用户按下添加到特定项目的购物车时,我都会使用Redux传递商品数据。在我的Cart
组件中,我可以查看添加到购物车的最后一项的项目选择数据。此用户选择项数据类似于Object {price: 25, item: "Hoodie", size: "medium"}
。我希望能够在我的Cart
组件中存储添加到购物车的每个选项。这是Cart
:
import React, { Component } from 'react';
import {addCart} from './Shop';
import { connect } from 'react-redux';
export class Cart extends Component {
constructor(props) {
super(props);
this.state = {items: this.props.cart,cart: [],total: 0};
}
itemBucket(item) {
this.state.cart.push(this.state.items);
this.countTotal();
}
countTotal() {
var total = 0;
console.log(this.state.cart);
this.state.cart.forEach(function(item, index){
total = total + item.price;
console.log (total);
})
}
componentDidMount () {
window.scrollTo(0, 0);
this.itemBucket();
}
render() {
return(
<div className= "Webcart" id="Webcart">
<addCart cartItem={this.props.cart} />
</div>
);
}
}
const mapDispatchToProps = (dispatch) => {
return {
onCartAdd: (cart) => {
dispatch(addCart(cart));
},
}
}
function mapStateToProps(state) {
return { cart: state.cart };
}
export default connect(mapStateToProps, mapDispatchToProps)(Cart);
我已将itemBucket()
设置为将每个项目选择添加到state
中的购物车数组中的功能。但是这不起作用,只传递添加到购物车的最后一项。这可能与改变我的Redux Store的工作方式有关,但我真的不知道如何应用它。这是我的Redux商店:
import { createStore, applyMiddleware } from 'redux';
import reducer from './reducers';
import thunkMiddleware from 'redux-thunk';
import {createLogger} from 'redux-logger';
const store = createStore(
reducer,
applyMiddleware(
createLogger(),
thunkMiddleware
)
);
export default store;
即使刷新或更改页面,如何保存传递给Cart
的每个项目?
修改
这是我的reducer组件:
import {ADD_CART} from './actions';
export default Reducer;
var initialState = {
cart:{},
data: [],
url: "/api/comments",
pollInterval: 2000
};
function Reducer(state = initialState, action){
switch(action.type){
case ADD_CART:
return {
...state,
cart: action.payload
}
default:
return state
};
}
答案 0 :(得分:2)
目前,您的应用中发生的事情是,每次刷新页面时,redux存储都会初始化并使用reducer提供的默认值。
您可以通过将对象作为createStore
的第二个参数来覆盖这些默认值。
const store = createStore(
reducer, // default values provided by reducers
{key: "value"}, // overwrites matching key/val pairs, think Object.assign with the first reducer argument
applyMiddleware(createLogger(), thunkMiddleware)
)
此示例使用浏览器的localStorage来存储和检索数据。
localStorage.js
文件使用redux状态作为要存储在localStorage中的数据。
localStorage.js
export const loadState = () => {
try {
let serializedState = localStorage.getItem('state')
if (serializedState === null) {
return undefined
}
let storageState = JSON.parse(serializedState)
return storageState
} catch (err) {
return undefined
}
}
export const saveState = (state) => {
try {
const serializedState = JSON.stringify(state)
// saves state to localStorage
localStorage.setItem('state', serializedState)
} catch (err) {
console.log('error and unable to save state', err)
}
}
现在你可以配置redux存储了,所以当它初始化时,会检索localStorage中的'state'项,并覆盖默认的reducer值。
saveState
函数将持续你的redux状态。它通过使用store.subscribe()
监听redux商店中的更改来实现此目的。进行更改时,系统会调用saveState
。
安装lodash以启用限制,否则saveState将被调用太多次。
<强> configureStore.js 强>
import { createStore, applyMiddleware } from 'redux'
import reducer from './reducers';
import thunkMiddleware from 'redux-thunk'
import createLogger from 'redux-logger'
import { loadState, saveState } from './localStorage'
import throttle from 'lodash/throttle'
let middlewares = [createLogger(), thunkMiddleware]
const configureStore = () => {
const localStorageState = loadState()
const store = createStore(
reducer,
localStorageState,
applyMiddleware(...middlewares)
)
// everytime the state changes, it will be saved to
store.subscribe(throttle(() => {
saveState(store.getState())
}, 1000))
return store
}
export default configureStore
现在按以下方式创建商店。
<强> index.js 强>
import configureStore from './configureStore'
const store = configureStore()
此实现演示了如何直接与localStorage交互,并从Dan那里获取了这个想法。您可以稍后优化此存储和检索过程。目前,只要在商店中发生更改,整个redux状态就会写入localStorage。
一旦您更接近为redux商店建立数据结构,您可以慢慢分解状态树并将它们设置为localStorage中的单个项目。 (一种可能的解决方案)
然后订阅/收听特定的状态树而不是整个商店,并在发生更改时保存它们。
store.getState().some.data.set
代替store.getState()
另外,检查npm,有些人已经创建了一些很酷的方法来解决这个问题。
答案 1 :(得分:2)
我的建议是使用redux-persist
将购物车状态保存到localStorage。与编写自己的实现相比,它会更容易,并且有一个活跃的社区(所以如果你遇到任何问题/错误,你可能不会是唯一的问题/错误。)
Redux商店
import { createStore, applyMiddleware, compose } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import reducer from './reducers';
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
const store = createStore(
reducer,
undefined,
compose(
applyMiddleware(createLogger(), thunkMiddleware),
autoRehydrate()
)
);
persistStore(store, { whitelist: ['cart'] });
export default store;
<强>减速强>
import { ADD_CART } from './actions';
import { REHYDRATE } from 'redux-persist/constants';
export default Reducer;
var initialState = {
cart:{},
data: [],
url: "/api/comments",
pollInterval: 2000
};
function Reducer(state = initialState, action){
switch(action.type){
case REHYDRATE:
if (action.payload && action.payload.cart) {
return { ...state, ...action.payload.cart };
}
return state;
case ADD_CART:
return {
...state,
cart: action.payload
}
default:
return state
};
}
请参阅此处的完整文档:https://github.com/rt2zz/redux-persist
答案 2 :(得分:1)
我将itemBucket()设置为一个函数,将每个项目选择添加到状态中找到的购物车数组中。但是这不起作用,只传递添加到购物车的最后一项。
使用
constructor(props) {
super(props);
this.state = {cart: this.props.cart,total: 0};
}
itemBucket(item) {
this.setState({cart : [...this.state.cart, item]});
}
componentDidUpdate(){
this.countTotal();
}
countTotal将显示旧购物车,如果放入itemBucket,因为setState不同步。你可以把它放在componentDidUpdate中。
对于刷新之间,通过使用服务调用将邮件存储在服务器上以发布计数,或使用localStorage / sessionStorage / indexedDb将其保留在客户端中。在componentWillMount中,从上面的位置获取此信息,并在客户端上使用它来补充您的redux商店。