2016-09-26 92 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