簡體   English   中英

在頁面刷新或更改時保存通過Redux傳遞的數據的問題

[英]Problems saving data passed through Redux when page refreshes or changes

每當此項目選擇添加到購物車時,我正在嘗試保存用戶的項目選擇。 每當用戶按下添加到特定項目的購物車時,我都會使用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 
    };
}

目前,您的應用中發生的事情是,每次頁面刷新時,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商店中的更改來實現此store.subscribe() 發生更改時,將調用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,有些人已經創建了一些很好的方法來解決這個問題。

我的建議是使用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

我將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商店。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM