reactjs - React Native : this. 可重用组件的状态不是预期的

标签 reactjs react-native

我是 React Native 的新手,说实话,我对 React 只有非常基本的了解。我正在开发一个示例应用程序,其中使用 reusable componentsES6 语法。

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

我发布我的代码是为了更好地理解。

这是我的主页,其中我使用了两次相同的自定义组件< 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>
    )
  }
}

我不明白为什么在我的 HomeScene 中使用的第一个 组件的 state.simplifiedCategories 在第二个 组件呈现后似乎是一个空数组。到目前为止,我认为这两个组件是完全隔离的,具有自己的“私有(private)”状态。但在这种情况下,似乎这是以某种方式共享的。

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

谢谢

编辑2016/09/05 根据用户 V-SHY 的建议,我尝试为每个组件提供一个随机字符串作为 key ,但这并不能解决问题。 我觉得很奇怪的是,我在全局窗口对象中只能看到 的一个实例,即最后一个。

此处的屏幕截图是指使用 进行的测试

 <TopCategories key="tc_first" {...this.props}/>

 <TopCategories key="tc_second" {...this.props}/>

HomeScene.js文件中

console.log(window) result

最佳答案

根据 Daniel 的建议,从服务器获取数据期间出现问题。特别是在 TopCategories.js 文件中创建 _topCategories=this 对象时我错了

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

关于reactjs - React Native : this. 可重用组件的状态不是预期的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39320230/

相关文章:

javascript - 类型错误 : state is not iterable on react and redux

javascript - 在 AsyncStorage React Native 上保存对象数组

javascript - 如何使用 Promise.all 等待两个请求,然后在回调中调用其他函数?

react-native - 无法使用 expo 和 genymotion 运行 android 应用程序

javascript - React JS 站点上的 Google Analytics 输出不正确的数据( session 中断?)

javascript - 如果使用 React 对象数组为空,如何显示消息?

javascript - react native : ListView with section headers and collapsible-expandable items

javascript - 通过使用 react-select 映射对象数组来生成选项

javascript - React-native 导入路径快捷方式问题

react-native - 如何在 react native 的模式中使用选项卡