我有两个组件:AddingAnimalPanel.js
和AnimalList.js
。我试图尝试执行以下操作:
在AddingAnimalPanel.js
中,我有一个按钮,一旦点击它,它就会调用一个函数_addAnimal()
并通过redux更新状态,更新后的状态会传递到AnimalList.js
并通过<ListView/>
列出州。
但是我收到错误:Cannot read property 'rowIdentities' of undefined
并且我没有为animalData
定义初始状态。所以我尝试将初始状态属性animalData
定义为数组,但我仍然遇到错误:Cannot read property 'length' of undefined
。
我似乎无法弄清楚出了什么问题。我做错了什么?
这是我的代码:
在AddingAnimalPanel.js
:
_addAnimal() {
var animals = [{animal: 'bird'}, {animal: 'cat'}, {animal: 'dog'}]
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
var animalData = ds.cloneWithRows(animals)
this.props.uploadAnimalData(animalData) //Calling action creator
}
在行动创作者中:
export const uploadAnimalData = (animalData) => {
return {
type: actionTypes.UPLOAD_ANIMAL_DATA,
animalData: animalData,
}
}
在减速器中:
const DEFAULT_STATE = {
//Tried also both animalData:[] and animalData:{} but still got the length error
}
export default function(state = DEFAULT_STATE, action) {
switch(action.type) {
case actionTypes.UPLOAD_ANIMAL_DATA:
return {
...state,
animalData: action.animalData
}
default:
return state
}
}
redux正常工作,道具传递到AnimalList.js
:
_renderRow(rowData){
return (
<AnimalListRow rowData={rowData} {...this.props}/>
)
}
render() {
return (
<View style={styles.container}>
<ListView
dataSource={this.props.animalData} //ListView is causing the error
renderRow={this._renderRow}
/>
</View>
)
}
}
编辑 - 附加代码
这是我目前为redux设置的。
减速器:
const DEFAULT_STATE = {
}
export default function(state = DEFAULT_STATE, action) {
switch(action.type) {
case actionTypes.UPLOAD_ANIMAL_DATA:
return {
...state,
animalData: action.animalData
}
default:
return state
}
}
export const getAnimalData = (state) => ({
animalData: state.animalData,
})
在名为connect
的单独文件中使用来自react-redux的index.js
,这就是animalData
传递给AnimalList.js
的方式:
// @flow
import AnimalList from './AnimalList'
import { connect } from 'react-redux'
import * as actions from './actions'
import {
getAnimalData,
} from '../../reducers/rootReducer'
const mapStateToProps = (state) => ({
...getAnimalData(state),
})
export default connect(mapStateToProps, actions)(AnimalList)
答案 0 :(得分:10)
我认为你走在正确的轨道上,这很可能是初始数据的问题。如果没有可执行的例子,很难确定确切的问题。
向ListView
提供任何对象或数组都不起作用。您必须向ds.cloneWithRows()
组件提供ds.cloneWithRowsAndSections()
或ListView
的结果。
可以采取多种行动方案。我建议的是将Listview.DataSource
- 功能更接近消耗的位置,即AnimalList
组件。您最初存储在Redux存储中的内容可能是一个空数组。来自react-redux的connect
,AnimalList.js
的要点可能是:
import { connect } from 'react-redux';
...
render() {
return (
<View style={styles.container}>
<ListView
dataSource={this.props.animalData} //ListView isn't causing an error
renderRow={this._renderRow}
/>
</View>
);
}
}
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
const mapStateToProps = (state) => {
return {
animalData: ds.cloneWithRows(state.animalReducer.animalData)
};
};
export default connect(mapStateToProps)(AnimalList);
实现相同结果的另一种方法是延迟ListView
组件的渲染并暂停DataSource
创建,直到animalData可用。例如AnimalList.js
:
static propTypes = {
animalData: React.PropTypes.array.isRequired
};
...
render() {
let animalListView = this.props.animalData.length >= 1
<ListView
dataSource={this.state.ds.cloneWithRows(this.props.animalData)}
renderRow={this._renderRow}
/> :
null;
return (
<View style={styles.container}>
{animalListView}
</View>
);
}
}
编辑:我发现您的代码存在更多潜在问题。
要将状态更改传播到reducer,您需要从Redux调用dispatch
。你可能想要在AddingAnimalPanel.js
中做什么:
_addAnimal() {
const { store } = this.context; // Assuming you're passing down a reference to store in context
var animals = [{animal: 'bird'}, {animal: 'cat'}, {animal: 'dog'}]
store.dispatch(this.props.uploadAnimalData(animals))
}
检查缩减器中的case actionTypes.UPLOAD_ANIMAL_DATA
是否因此而被触发。
使用您发布的其他代码,如果我设法正确地为您的代码做好了准备,AnimalList.js
:
render() {
return (
<View style={styles.container}>
<ListView
dataSource={this.props.animalData} //ListView isn't causing an error
renderRow={this._renderRow}
/>
</View>
);
}
}
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
const mapStateToProps = (state) => ({
animalData: ds.cloneWithRows(...getAnimalData(state)),
})
export default connect(mapStateToProps, actions)(AnimalList)
我将做的是设置
const DEFAULT_STATE = {
animalData: []
}
在您的减速机中。这种方式state.animalData
始终是常规数组,AnimalList
组件处理数据转换为格式ListView
期望接收数据。
如果设置仍然不清楚,请尝试查找例如GitHub并浏览该代码以了解它是如何连接在一起的。
答案 1 :(得分:0)
尝试以下内容并告诉我们。首先,像你一样把减速器中的初始状态放回原处:
const DEFAULT_STATE = {
animalData:[]
}
然后,在reducer中尝试以下代码:
case actionTypes.UPLOAD_ANIMAL_DATA:
return Object.assign({}, state, {
animalData: action.animalData,
})
最后,在mapStateToProps
中使用state.animalData
访问列表。最后一部分可能不需要,我只是不确定你的getAnimalData
是如何使用的。
希望它有所帮助。