如何在React-Redux中的组件的每个实例上调用mapStateToProps

时间:2018-06-29 20:17:30

标签: react-native react-redux

我有一个名为AuditionItem的组件,该组件的多个实例被添加到了名为AuditionsList的父组件中。

我已完成导出默认的connect(mapStateToProps)(AuditionItem)

根据我的经验,仅对一个AuditionItem实例(启动状态更改的一个实例)调用mapStateToProps。但我希望为AuditionItem的每个实例调用mapStateToProps。

有没有办法做到这一点?

这是我的AuditionItem.js代码:

false

以及父AuditionsList.js的代码

import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import Moment from 'moment';
import colors from './../styles/colors';
import { store } from './../App';
import { addBookmark, removeBookmark } from './../actions/creators';
import { connect } from 'react-redux';

class AuditionItem extends React.Component {

  _toggleBookmark = (auditionId, bookmarked) => {
    if(bookmarked)
      store.dispatch(removeBookmark(auditionId));
    else
      store.dispatch(addBookmark(auditionId));
  }

  render() {
    Moment.locale('en');

    let bookmarked = (this.props.auditions.indexOf(this.props.auditionId) > -1) ? true : false;

    let roleString = String(this.props.role);
    if(roleString.length > 35)
      roleString = roleString.substring(0, 35) + " ...";
    let projectString = String("Project: (" + this.props.productionType + ") " + this.props.project);
    if(projectString.length > 35)
      projectString = projectString.substring(0, 35) + " ...";
    let productionHouseString = String("Production House: " + this.props.productionHouse);
    if(productionHouseString.length > 35)
      productionHouseString = productionHouseString.substring(0, 35) + " ...";
    let iconName = `ios-bookmark${bookmarked ? '' : '-outline'}`;

    return (
      <View style={styles.auditionItemWithBookmark}>
        <View style={styles.bookmark}>
          <TouchableOpacity onPress={() => this._toggleBookmark(this.props.auditionId, bookmarked)} >
            <Ionicons name={iconName} size={25} />
          </TouchableOpacity>
       </View>
        <View style={styles.auditionItem}>
          <Text style={styles.role}>{roleString}</Text>
          <Text style={styles.project}>{projectString}</Text>
          <Text style={styles.productionHouse}>{productionHouseString}</Text>
          <Text style={styles.auditionDate}>Begins: {Moment(String(this.props.auditionDate).replace('"','').replace('"', '')).format('LLLL')}</Text>
        </View>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  auditionItemWithBookmark: {
    flex: 1,
    flexDirection: "row",
    backgroundColor: colors.auditionItemBackgroundColor,
    borderRadius: 10,
    margin: 10,
    padding: 15,
  },
  bookmark: {
    flex: 1,
    paddingTop: 5,
  },
  auditionItem: {
    flex: 8,
    flexDirection: "column",
    backgroundColor: colors.auditionItemBackgroundColor,
  },
  role: { color: colors.auditionItemColor, fontSize: 20, fontWeight: "bold" },
  project: { color: colors.auditionItemColor },
  productionHouse: { color: colors.auditionItemColor },
  auditionDate: { color: colors.auditionItemColor },
});

const mapStateToProps = state => {
  return {
    auditons: state.bookmarks.auditions,
  }
}

export default connect(mapStateToProps)(AuditionItem);

App.js代码:

import React from 'react';
import { Text, View, FlatList, ActivityIndicator } from 'react-native';
import { connect } from 'react-redux';
import AuditionItem from './AuditionItem';
import Auditions from './../data/Auditions';
import { store } from './../App';

class AuditionsList extends React.Component {

    constructor(props) {
      super(props);
      this.state = { isLoading: true, data: []  }
    }

    componentDidMount() {
      this._refreshData();
    }

    componentDidUpdate(prevProps) {
      if((this.props.location !== prevProps.location) || (this.props.roleType !== prevProps.roleType))
        this._refreshData();
    }

    _onRefresh() {
      this.setState({ isLoading: true }, this._refreshData() );
    }

    _refreshData = () => {
        Auditions.fetchAuditions(this.props.productionType, this.props.location, this.props.roleType).then(auditions => {
          this.setState({ isLoading: false, data: this._addKeysToAuditions(auditions) });
        });
    }

    _addKeysToAuditions = auditions => {
      return auditions.map(audition => {
          return Object.assign(audition, { key: audition.Role});
      });
    }

    _renderItem = ({ item }) => {
      return (
        <AuditionItem
          auditionId={item.objectId}
          role={item.Role}
          project={item.Project.Name}
          productionType={item.Project.ProductionType.Type}
          auditionDate={JSON.stringify(item.Date.iso)}
          productionHouse={item.Project.ProductionHouse.Name}
          auditions={store.getState().bookmarks.auditions}
        />
      );
    }

    render() {
      if (this.state.isLoading) {
        return (
          <View style={{flex: 1, paddingTop: 20}}>
            <ActivityIndicator />
          </View>
        );
      }

      return (
        <View style={{ flex: 1 }}>
          <FlatList onRefresh={() => this._onRefresh()} refreshing={this.state.isLoading} data={this.state.data} renderItem={this._renderItem} />
       </View>
      );
    }

}

const mapStateToProps = state => {
  return {
    location: state.settings.location,
    roleType: state.settings.roleType,
  };
}

export default connect(mapStateToProps)(AuditionsList);

1 个答案:

答案 0 :(得分:1)

这不会创建类的实例,它只会导出类/对象。

export default connect(mapStateToProps)(AuditionItem)

Export reference

在调用类的构造函数时会得到实例,但这是在导入实例之后。因此,基本上,每次您在内部使用导入的AuditionItem(即)React时,都在创建该类的新实例。

我想问题可能出在AuditionItem本身,或者是您要传递给的道具。

  

有关mapStateToProps的其他信息   来自official Redux文档

     

[mapStateToProps(state,[ownProps]):stateProps](函数):如果指定了此参数,则新组件将订阅Redux存储更新。这意味着每当商店更新时,都会调用mapStateToProps。 mapStateToProps的结果必须是一个普通对象,该对象将合并到组件的props中。如果您不想订阅商店更新,请传递null或undefined代替mapStateToProps。