您好我有这个对象,并且会对它做一些数学/统计操作。现在我有问题:
如何访问它?例如,我想访问数字[0] ['B1'] 当我做{this.props.numbers [0] ['B1']}时,我得到:无法读取未定义的属性B1。
如果我想对这些数字进行一些计算,我会把它们放在哪里?根据我对react redux的有限经验,我知道我不应该在减速器中做任何类似的事情,对吗?我会为例如创建更多动作(动作创建者)吗?获得平均B1数,或对数字进行任何统计操作等。是否建议使用“重新选择”来完成此类任务?
numReducer
import { LIST_NUMBERS, PICK_NUMBER, GET_DATA } from '../actions/actionTypes';
export default (state = [], action = {}) => {
switch (action.type) {
case LIST_NUMBERS:
return action.payload || [];
case PICK_NUMBER:
return action.payload;
case GET_DATA:
return action.payload;
default:
return state;
}
};
动作:
import { LIST_NUMBERS, PICK_NUMBER, GET_DATA } from './actionTypes';
import dataSet from '../data.json';
export const listNumbers = () => {
const nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
return {
type: LIST_NUMBERS,
payload: nums
};
};
export const getData = () => {
return {
type: GET_DATA,
payload: dataSet
};
};
export const pickNumber = (num) => {
return {
type: PICK_NUMBER,
payload: num
};
};
data.json
[
{
"DrawDate": "22-Mar-17",
"B1": 12,
"B2": 6,
"B3": 11,
"B4": 31,
"B5": 27,
"B6": 19,
"BB": 42,
"BS": 1,
"DrawNumber": 2217
},
{
"DrawDate": "18-Mar-17",
"B1": 26,
"B2": 37,
"B3": 8,
"B4": 3,
"B5": 19,
"B6": 41,
"BB": 43,
"BS": 3,
"DrawNumber": 2216
},
....
Home Container
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { listNumbers, pickNumber, getData } from '../actions/numberActions';
import Home from '../components/Home';
const mapStateToProps = state => ({
numbers: state.numbers
});
const mapDispatchToProps = dispatch => (
bindActionCreators({
listNumbers,
pickNumber,
getData
}, dispatch)
);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Home);
主页组件:
import React, { Component } from 'react';
import { View, Text, Button, TextInput } from 'react-native';
export default class Home extends Component {
static navigationOptions = {
title: 'Home Screen',
};
componentDidMount() {
this.props.getData();
}
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Text>####################</Text>
<Text>Intro Screen</Text>
<Text>Number: {this.props.numbers[0]['B1']}</Text>
</View>
);
}
}
EDIT / ADDITION:
根据以下建议,我已将生命周期方法更改为ComponentWillMount,并添加了一个检查以查看是否已加载this.props.numbers。
import React, { Component } from 'react';
import { View, Text, Button, TextInput } from 'react-native';
export default class Home extends Component {
static navigationOptions = {
title: 'Home Screen',
};
componentWillMount() {
this.props.getData();
}
render() {
if (!this.props.numbers) {
console.log('not yet loaded'); // or a spinner?
}
const { navigate } = this.props.navigation;
return (
<View>
<Text>####################</Text>
<Text>Intro Screen</Text>
<Text>Number: {this.props.numbers[0]['B1']}</Text>
</View>
);
}
}
我仍然得到同样的错误:无法读取未定义的属性'B1'。此外,控制台不会记录“尚未加载”,这表示数字对象存在 - 我只是在访问它时出错。
EDIT2:
import React, { Component } from 'react';
import { View, Text, Button, TextInput } from 'react-native';
export default class Home extends Component {
static navigationOptions = {
title: 'Home Screen',
};
componentWillMount() {
this.props.getData();
}
listNums() {
return this.props.numbers.map((num) => num['B1']);
}
listSingleNum() {
return this.props.numbers[0]['B1'];
}
render() {
if (!this.props.numbers) {
console.log('not yet loaded'); // or a spinner?
} else {
console.log(this.listNums());
}
const { navigate } = this.props.navigation;
return (
<View>
<Text>####################</Text>
<Text>Intro Screen</Text>
<Text>Number: {this.listNums()}</Text>
</View>
);
}
}
因此listNums()可以正常显示每个元素的B1,但是如果我尝试访问listSingleNum中的单个B1元素,则会抛出前面提到的错误:ExceptionsManager.js:63无法读取未定义的属性“B1”。
答案 0 :(得分:2)
我如何访问它?例如,我想访问数字[0] ['B1']当我这样做{this.props.numbers [0] ['B1']}时,我得到:无法读取未定义的属性B1。
看起来你的所有react / redux接线都很好,只是在getData
中调用了componentDidMount
,所以对于第一次渲染,数据还不存在(参见文档) lifecycle methods order)。您可以使用componentWillMount
代替,但我仍然不确定数据是否可用于第一次渲染。为了安全起见,如果numbers
为undefined
,请更改渲染函数以执行不同的操作(如果最终从某个后端加载数据,则必须执行此操作)。
注意:以下内容不正确 - 请参阅下面的编辑
render() {
if (!this.props.numbers) {
return null; // or a spinner?
}
const { navigate } = this.props.navigation;
return (
<View>
<Text>####################</Text>
<Text>Intro Screen</Text>
<Text>Number: {this.props.numbers[0]['B1']}</Text>
</View>
);
}
如果我想对这些数字进行一些计算,我会把它们放在哪里?根据我对react redux的有限经验,我知道我不应该在减速器中做任何类似的事情,对吗?我会为例如创建更多动作(动作创建者)吗?得到平均B1数,或对数字的任何统计操作等。是否建议使用“重新选择”来完成这类任务?
这取决于计算的密集程度。如果它非常便宜,我只需在渲染功能中执行它们
import calculateAverage from './somewhere'
...
return (
<View>
<Text>####################</Text>
<Text>Intro Screen</Text>
<Text>Number: {this.props.numbers[0]['B1']}</Text>
<Text>Average: {calculateAverage(this.props.numbers.map((data) => data['B1'])}</Text>
</View>
);
如果计算成本很高,则重新选择是一个不错的选择,这样它就不会在每次渲染时不必要地重新计算值。它比测试组件本身的逻辑更好。
编辑:哇......此刻我感觉有点傻了......
this.props.numbers
未定义(由reducer的初始状态定义)。如果检查长度,它将呈现(我已经复制了所有这些代码并自己运行以确保这一次)。
render() {
if (this.props.numbers.length === 0) {
return null; // or a spinner?
}
const { navigate } = this.props.navigation;
return (
<View>
<Text>####################</Text>
<Text>Intro Screen</Text>
<Text>Number: {this.props.numbers[0]['B1']}</Text>
</View>
);
}
在if语句中实际返回一些内容(或null
)非常重要,这样它就不会达到undefined
值(this.props.numbers[0]
)。
解释(在评论中提出要求)
这一切归结为component's lifecycle。
当组件安装时,它有一个空数组,由reducer的initialState
设置
export default (state = [], action = {}) => {
...
};
mounting lifecycle methods将按顺序触发。当componentDidMount
(或componentWillMount
取决于我们所处的问题的更新时)状态将在redux存储中被替换为具有完整数据集。
安装生命周期完成后,react-redux将更改触发道具更改,触发updating lifecycle methods。
在此阶段,再次调用渲染,这次使用正确的数据。
因此组件不会“继续重新渲染,直到数字对象不为空”,只要道具发生变化,它就会重新渲染,如果数组数组不为空,则会包含所需的组件。
返回null
为valid in react,通常用于阻止组件尝试访问尚未提供的道具。