2016-09-26 129 views
9

我碰到了一堵牆,試圖找出爲什麼我要獲取和存儲狀態的JSON數據沒有映射到我的組件道具,但在mapStateToProps()函數中出現console.log()時出現。我做錯了什麼,我沒有看到這裏?mapStateToProps()在Redux應用程序嵌套狀態的狀態?

編輯:顯然狀態屬性被映射到組件,但嵌套。 data財產,從mapStateToProps()登錄時,必須通過state.state.data訪問。在此之前(請參閱減速器),當記錄action.data時,數據按預期顯示。沒有奇怪的嵌套。 connect功能可能有問題嗎?

瞭解如何有狀態對象中填充的狀態屬性:

See the data property populated within the state object

下面是我的組件:

class ViewSelector extends Component { 
    componentWillMount() { 
    this.props.fetchDataAsync('VIEW ALL'); 
    } 

    selectView(event) { 
    // this.props.data comes up undefined despite state being mapped 
    // to the component props 
    console.log('props: ' + this.props.data); 
    this.props.filterData(event.target.innerHTML, this.props.data); 
    } 

    render() { 
    return (
     <section> 
     <nav> 
      <button onClick={this.selectView.bind(this)}>VIEW ALL</button> 
      <button onClick={this.selectView.bind(this)}>VIEW LAST WEEK</button> 
      <button onClick={this.selectView.bind(this)}>VIEW LAST MONTH</button> 
     </nav> 
     <Dashboard data={this.props.data}/> 
     </section> 
    ); 
    } 
} 

function mapStateToProps(state) { 
    console.log(state); 
    // this console.log shows the state with the data property. 
    return { 
    data: state.data 
    }; 
} 

export default connect(mapStateToProps, actions)(ViewSelector); 

編輯:這裏是澄清減速:

import { 
    FETCH_DATA, 
    FETCH_DATA_SUCCESS, 
    FETCH_DATA_FAILURE, 
    FILTER_DATA 
} from '../actions/types'; 
import { getLastWeek, getLastMonth } from './reducer_helper'; 

const initialState = { 
    error: '', 
    loading: false, 
    data: [] 
}; 

/* eslint-disable */ 
const app = (state = initialState, action) => { 
    switch(action.type) { 
    case FETCH_DATA: 
     return { ...state, error: '', loading: true }; 
    case FETCH_DATA_SUCCESS: 
     // console.log(action.data) returns data as expected. 
     // no nesting...until it hits the mapStateToProps() function 
     return { ...state, error: '', loading: false, data: action.data }; 
    case FETCH_DATA_FAILURE: 
     return { ...state, error: action.error, loading: false }; 
    case FILTER_DATA: 
     let data; 
     if (action.view === 'VIEW LAST WEEK') { 
     data = getLastWeek(state.data); 
     } else if (action.view === 'VIEW LAST MONTH') { 
     data = getLastMonth(state.data); 
     } else { 
     data = state.data; 
     } 
     return { ...state, error: '', loading: false, data }; 
    } 
    return state; 
} 

export default app; 

動作創作者的澄清對派遣到減速機:

export function fetchData() { 
    return { 
    type: FETCH_DATA 
    }; 
} 

export function fetchDataSuccess(data) { 
    return { 
    type: FETCH_DATA_SUCCESS, 
    data: data 
    }; 
} 

export function fetchDataFailure(data) { 
    return { 
    type: FETCH_DATA_FAILURE, 
    data 
    }; 
} 

export function filterData(view) { 
    return { 
    type: FILTER_DATA, 
    view 
    }; 
} 

export function fetchDataAsync() { 
    return dispatch => { 
    dispatch(fetchData()); 

    axios.get(DATA_URL) 
    .then(res => { 
     dispatch(fetchDataSuccess(res.data)); 
    }).catch(err => { 
     dispatch(fetchDataFailure(err)); 
    }); 
    }; 
} 

如何將整個應用正在呈現&的終極版店:

import React from 'react'; 
import ReactDOM from 'react-dom'; 
import { Provider } from 'react-redux'; 
import { createStore, applyMiddleware } from 'redux'; 
import thunk from 'redux-thunk'; 

import App from './components/app'; 
import reducers from './reducers'; 

const createStoreWithMiddleware = applyMiddleware(thunk)(createStore); 

ReactDOM.render(
    <Provider store={createStoreWithMiddleware(reducers)}> 
    <App /> 
    </Provider> 
    , document.querySelector('.container')); 
+0

mapStateToProps應該獲得完整的狀態作爲參數,你到底在問什麼? – StateLess

+0

當我返回'{data:state.data}'數據數組存在時。但是當我嘗試使用'this.props.data'訪問組件內的數據時,它會出現未定義的情況。所以它*看起來像是沿着道路某處正在迷路。或者我完全誤解了mapStateToProps正在做什麼...... – Jose

+0

你可以嘗試登錄渲染並檢查一次 – StateLess

回答

7

太多審查,調試,並要求其他開發者後,簡單地說,這是我面臨的問題:減速以及它是如何被導入到主「清單「文件來管理所有其他減速器。

基本上,因爲我在這個項目中只使用一個減速器,所以不需要清單減速器文件。見下:

import { combineReducers } from 'redux'; 
import Reducer from './reducer'; 

const rootReducer = combineReducers({ 
    state: Reducer 
}); 

export default rootReducer; 

我不知道爲什麼這是嵌套狀態。也許是因爲在理論上,我們會處理具有不同目的的多個reducer(如數據縮減器和用戶reducer),並需要將這些嵌套到我們的狀態樹中進行管理。

state = { 
    // here is one nested reducer with its own properties 
    data: { 
    type: // somevalue, 
    filtered: true 
    }, 
    // here is another 
    user: { 
    name: // somename, 
    password: // somepassword 
    } 
}; 

總之...請注意您的減速器是如何導入到您的createStore函數中的,以及是否使用了僅減速器或者是否有多個減速器通過各種清單文件運行。

乾杯。

+0

combineReducers根據所使用的鍵嵌套每個reducer的狀態(所以在狀態下,對於Reducer,在上面的代碼中)。在你的情況下,你不應該調用combineReducers,因爲你只有一個reducer。在一個非平凡的應用程序中,你可能會有很多reducer,每個都使用一個描述性鍵(例如,不叫'state',但是在你的域名後面調用)。 – TomW

5

所以你的datamapStateToProps值返回一個對象。你可能想這個:

function mapStateToProps(state) { 
    console.log(state); 
    // this console.log shows the state with the data property. 
    return { 
    ...state.app 
    }; 
} 

這會給你訪問你的data減速機等領域。此外,從示例中不清楚您將如何使用數據,或者包含哪些字段。另外,首先,您的reducer未初始化爲將使用的字段的空值或空值,這肯定會導致錯誤。可能更好地開始與initialState對象:

const initialState = { 
    error: '', 
    loading: false, 
    data: [] 
}; 

const app = (state=initialState, action) => { 
/* .... */ 
+0

你說得對。你看起來有一半的答案。我剛纔從@ cema-sp注意到的一點是,出於某種原因,有一個狀態對象嵌套在另一個狀態對象中。所以一切都顯示爲'state.state.data'或'state.state.error'而不是'state.data'。我的減速機出了問題,但我不確定。 – Jose