React Native:不期望的可重用组件的this.state

时间:2016-09-04 18:33:38

标签: reactjs react-native

我是React原生的新手,说实话,我对React有一个非常基本的了解。我正在开发一个示例应用程序,其中我使用reusable components ES6 sintax。

在同一场景中多次重复使用同一组件时,我遇到了意外的结果(我也使用了Navigator)。更准确地说,我无法理解为什么不同组件(相同类型)显然是彼此状态的条件。

我发布了我的代码以便更好地理解。

这是我的主页,我使用相同的自定义组件< 2的2倍TopCategories />

HomeScene.js

import React from 'react';
import {View} from 'react-native';

import BaseScene from './BaseScene'
import SearchSuggest from '../components/SearchSuggest';
import TopCategories from '../components/TopCategories'

import styles from '../styles'


export default class HomeScene extends BaseScene {
  render() {
    return(
      <View style={styles.container}>
        <SearchSuggest
          navigator={this.props.navigator}
        />

        <TopCategories/> //first 

        <TopCategories/> //second

      </View>
    )
  }
}

这些是使用的内部组件的详细信息:

TopCategories.js

import React, { Component } from 'react';
import {
  Text,
  View,
  StyleSheet
} from 'react-native';

import styles from '../styles'
import utility from '../utility'
import serverConnector from '../serverConnector'
import routes from '../routes'

import MenuItemComplex from './MenuItemComplex'

export default class TopCategories extends Component {

  constructor(props) {
    super(props);
    this.state = {categories: []};
    this._fetchContent();
  }


  _updateCategoriesList(rawCategories){
    //store in state.categories array a simplied version of         
    //the contents received from the server

    let simplifiedCategories = [];
    for(i=0; i<rawCategories.length; i++){
      var simpleCat = {};
      simpleCat.id = rawCategories[i].uniqueID;
      simpleCat.name = rawCategories[i].name;
      simplifiedCategories.push(simpleCat);
    }

    this.setState({categories: simplifiedCategories });
  }

  _fetchContent(){
    //fetch content from server in JSON format 
    _topCategories = this;
    serverConnector.call(
      "CATEGORY",
      "FindTopCategories",
      {},
      function(err, json){
        if(err!=null) utility.log("e", err);
        else {
          try{
            _topCategories._updateCategoriesList(json.res.header.body.CatalogGroupView);
          }catch(err){
            utility.log("e", err);
          }
        }
      }
    )
  }

  openCategoryScene(id, name){
    //push on Navigator stack the next route with additional data
    let nextRoute = routes.get("categoriesListFirst");
    nextRoute.passProps = {
      categoryId: id,
      categoryName: name
    };
    this.props.navigate(nextRoute)
  }

  render(){
    console.log(this.state)
    return (
      <MenuItemComplex key="categories" name="Catalogo" icon="list-b" onItemSelected={this.openCategoryScene.bind(this)} subItems={this.state.categories} />
    )
  }
}

最后 MenuItemComplex.js

import React, { Component } from 'react';
import { View, Text, Image, TouchableHighlight, TouchableWithoutFeedback } from 'react-native';

import styles from '../styles'

export default class MenuItemComplex extends Component{

  static propTypes = {
    name : React.PropTypes.string.isRequired,
    icon : React.PropTypes.string.isRequired,
    subItems: React.PropTypes.array.isRequired,
    onItemSelected: React.PropTypes.func.isRequired
  };

  render(){
    let subItems = [];
    for(i=0; i<this.props.subItems.length; i++){
      let subItem = this.props.subItems[i];
      subItems.push(
        <TouchableHighlight
          key={subItem.id}
          underlayColor={"#d00"}
          activeOpacity={1}
          onPress={() => this.props.onItemSelected(subItem.id, subItem.name)}
        >
          <View style={styles.menuSubItem}>
            <Text style={[styles.mmText, styles.menuSubItemText]} >
                {subItem.name}
            </Text>
          </View>
        </TouchableHighlight>
      )
    }

    return(

      <View>
        <TouchableWithoutFeedback disabled={true}>
          <View style={styles.menuItem}>
            <Image style={styles.menuItemImage} source={{uri: this.props.icon}} />
            <Text style={[styles.mmTextBold, styles.menuItemText]}>{this.props.name}</Text>
          </View>
        </TouchableWithoutFeedback>

        {subItems}

      </View>
    )
  }
}

我无法理解为什么第一个&lt;的state.simplifiedCategories。 TopCategories&gt;我的HomeScene中使用的组件在第二个&lt;之后似乎是一个空数组。 TopCategories&gt;组件已呈现。到目前为止,我认为这两个组件是完全孤立的,有自己的&#34;私有&#34;州。但在这种情况下似乎是以某种方式共享。

有人可以解释这里发生了什么吗?然后我该如何解决这个问题呢?

由于

编辑2016/09/05 正如用户V-SHY所建议的那样,我试图给每个组件一个随机字符串作为键,但这并没有解决问题。 我觉得非常奇怪的是,我只能看到&lt; TopCategories&gt;在全局窗口对象中,最后一个。

此处的屏幕截图是指使用

进行的测试
 <TopCategories key="tc_first" {...this.props}/>

 <TopCategories key="tc_second" {...this.props}/>
HomeScene.js 文件中的

console.log(window) result

1 个答案:

答案 0 :(得分:2)

根据Daniel的建议,在从服务器获取数据时出现了问题。特别是在 TopCategories.js 文件

中创建_topCategories =此对象时出错了
_fetchContent(){
    _topCategories = this; // ISSUE HERE!
    serverConnector.call(
      "CATEGORY",
      "FindTopCategories",
      {},
      function(err, json){
        if(err!=null) utility.log("e", err);
        else {
          try{
            _topCategories._updateCategoriesList(json.res.header.body.CatalogGroupView);
          }catch(err){
            utility.log("e", err);
          }
        }
      }
    )
  }

我解决了将fetchContent方法传递给组件的引用:

constructor(props) {
    super(props);
    this.state = {categories: []};
    this._fetchContent(this); // passing THIS reference
  }


  _updateCategoriesList(rawCategories){
    let simplifiedCategories = [];
    for(i=0; i<rawCategories.length; i++){
      var simpleCat = {};
      simpleCat.id = rawCategories[i].uniqueID;
      simpleCat.name = rawCategories[i].name;
      simplifiedCategories.push(simpleCat);
    }

    this.setState({categories: simplifiedCategories});
  }

  _fetchContent(instanceRef){
    motifConnector.call(
      "CATEGORY",
      "FindTopCategories",
      {},
      function(err, json){
        if(err!=null) utility.log("e", err);
        else {
          try{
            instanceRef._updateCategoriesList(json.res.header.body.CatalogGroupView);
          }catch(err){
            utility.log("e", err);
          }
        }
      }
    )
  }