У меня есть компонент с именем AuditionItem, несколько экземпляров которого добавляются в родительский компонент с именем AuditionsList.
Я сделал экспорт по умолчанию подключиться (mapStateToProps) (AuditionItem)
Из моего опыта mapStateToProps вызывается только для одного экземпляра AuditionItem (тот, который инициирует изменение состояния). Но я хочу, чтобы mapStateToProps вызывался для КАЖДОГО экземпляра AuditionItem.
Есть ли способ сделать это?
Вот мой код для AuditionItem.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);
И код для родительского AuditionsList.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);
Код для App.js:
import React from 'react';
import { Text, View, ActivityIndicator } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { Header } from 'react-native-elements';
import { createMaterialBottomTabNavigator } from 'react-navigation-material-bottom-tabs';
import { SettingsDividerShort, SettingsCategoryHeader, SettingsPicker} from 'react-native-settings-components';
import BookmarksScreen from './screens/BookmarksScreen';
import AuditionsScreen from './screens/AuditionsScreen';
import SettingsScreen from './screens/SettingsScreen';
import { AsyncStorage } from "react-native";
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import rootReducer from './reducers/index';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/lib/integration/react';
import { autoMergeLevel2 } from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const persistConfig = {
key: 'root',
storage: AsyncStorage,
stateReconciler: autoMergeLevel2,
whitelist: ['settings', 'bookmarks']
};
const pReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(pReducer);
export const persistor = persistStore(store);
const MaterialBottomTabNavigator = createMaterialBottomTabNavigator(
{
Bookmarks: BookmarksScreen,
Auditions: AuditionsScreen,
Settings: SettingsScreen,
},
{
shifting: true,
initialRouteName: 'Auditions',
barStyle: { backgroundColor: 'black' },
}
);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<PersistGate loading={<ActivityIndicator />} persistor={persistor}>
<MaterialBottomTabNavigator />
</PersistGate>
</Provider>
)
}
}