【问题标题】:react-native redux accessing / manipulating an objectreact-native redux 访问/操作对象
【发布时间】:2017-03-26 10:15:40
【问题描述】:

您好,我有这个对象,并将对其进行一些数学/统计运算。现在我要提问:

  1. 如何访问它?例如我想访问 numbers[0]['B1'] 当我执行 {this.props.numbers[0]['B1']} 时,我得到:无法读取未定义的属性 B1。

  2. 如果我想对这些数字进行一些计算,我会将它们放在哪里?根据我对 react redux 的有限经验,我知道我不应该在 reducer 中做类似的事情,对吗?我会创建更多的动作(动作创建者),例如。获取平均 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
  };
};

数据.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
  },
....

主容器

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>
    );
  }

}

编辑/添加:

根据下面的建议,我已将生命周期方法更改为 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:63Cannot read property 'B1' of undefined。

【问题讨论】:

  • console.log(this.props.numbers) 是什么样的?也许它是一个空数组? (´![] === false´)
  • 我已经更新了问题。回答您的问题:它在 console.log 中显示了两次。第一次是 [ ],第二次是应有的整个数组。

标签: json react-native react-redux


【解决方案1】:

如何访问它?例如,我想访问 numbers[0]['B1'] 当我执行 {this.props.numbers[0]['B1']} 时,我得到:无法读取未定义的属性 B1。

看起来你所有的 react/redux 接线都很好,只是 getDatacomponentDidMount 中被调用,所以对于第一次渲染,数据还不存在(参见 lifecycle methods order 的文档) .您可以改用componentWillMount,但我仍然不确定数据在第一次渲染时是否可用。为了安全起见,如果 numbersundefined,则更改渲染函数以执行不同的操作(如果最终从某个后端加载数据,则无论如何都必须这样做)。

注意:以下内容不正确 - 请参阅下面的编辑

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 的有限经验,我知道我不应该在 reducer 中做类似的事情,对吗?我会创建更多的动作(动作创建者),例如。获取平均 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])。


说明(在 cmets 中要求)

这一切都归结为component's lifecycle

当组件挂载时它有一个空数组,由reducer的initialState设置

export default (state = [], action = {}) => {
  ...
};

mounting lifecycle methods 将按顺序触发。当componentDidMount(或componentWillMount,取决于我们所在问题的更新)时,redux 存储中的状态被替换以拥有完整的数据集。

在挂载生命周期完成后,react-redux 将更改触发 props 更改,触发 updating lifecycle methods

在此阶段再次调用渲染,这次使用正确的数据。

所以组件不会“一直重新渲染,直到 numbers 对象不为空”,它会在 props 更改时重新渲染,如果 numbers 数组不为空,将包含所需的组件。

返回nullvalid in react,通常用于防止组件尝试访问尚不可用的道具。

【讨论】:

  • 谢谢 - 有效点不幸的是我不认为这是这种情况。我已经更新了问题。
  • 你看到你的日志信息了吗?如果您不在该块内返回,您仍然会收到未定义的错误。
  • 好的。那行得通——所以坚持住。它是如何工作的?它会一直重新渲染直到数字对象不为空吗?
  • 我在答案中添加了解释,但基本上归结为组件生命周期。
猜你喜欢
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 2016-07-04
  • 2017-02-01
  • 1970-01-01
相关资源
最近更新 更多