Заранее благодарю за помощь - я очень новичок в разработке приложений.
В моем приложении React Native есть навигатор по вкладкам с тремя вкладками, одна для канала, одна для списка событий иодин для списка пользователей.Когда я переключаюсь со своей вкладки фида - которая отображает список сообщений - обратно на вкладку моих пользователей и нажимаю на элемент списка, чтобы просмотреть профиль пользователя, я получаю следующую ошибку: Ошибка при нажатии на элемент списка
Я подозреваю, что эта проблема как-то связана с тем, как я создал списки.
Для моей вкладки фида, вот как я определяю свой список сообщений:
renderFeed = () => {
if (this.props.loadingList) {
return <Spinner />;
} else if (this.props.error) {
return (<Text>{this.props.error}</Text>);
} return (
<List
enableEmptySections
dataArray={this.props.feedData}
renderRow={this.renderPost}
/>
);
}
renderPost = (post) => {
const { name, postContent, time } = post;
return (
<Card style={{ flex: 0 }}>
<CardItem>
<Left>
<Thumbnail source={{ uri: 'https://cdn.images.express.co.uk/img/dynamic/4/590x/LeBron-James-has-until-June-29-to-opt-out-of-his-contract-with-the-Cavaliers-978390.jpg?r=1529715616214' }} />
<Body>
<Text>{name}</Text>
<Text note>{time}</Text>
</Body>
</Left>
</CardItem>
<CardItem>
<Body>
<Text>{postContent}</Text>
</Body>
</CardItem>
</Card>
);
}
Для моей вкладки пользователей, вот как я определяю свой список пользователей:
renderActivesList = () => {
if (this.props.loadingList) {
return <Spinner />;
} else if (this.props.error) {
return (<Text>{this.props.error}</Text>);
} return (
<List
enableEmptySections
dataArray={this.props.listData}
renderRow={this.renderRow}
/>
);
}
renderRow = (active) => {
const name = `${active.firstName} ${active.lastName}`;
return (
<ListItem
key={name}
button
onPress={() => { this.onActiveSelect(name, active.rank); }}
>
<Body>
<Text>{name}</Text>
<Text note>{active.position}</Text>
</Body>
<Right>
<Text note>{active.rank}</Text>
</Right>
</ListItem>
);
}
Я чувствую, что здесь должен быть какой-то конфликт, так как ошибка возникает только при нажатии на пользователяиз списка пользователей, и только ПОСЛЕ того, как я переключаюсь на вкладку канала (и, следовательно, отображаю ее).
Пожалуйста, дайте мне знать ваши мысли.Спасибо!
ОБНОВЛЕНИЕ 1:
Я попытался использовать опору списка 'keyExtractor', чтобы сгенерировать ключ для каждого элемента списка.Однако произошла та же ошибка.Если это важно: компонент «Список», который я здесь использую, взят из библиотеки Native-Base.
ОБНОВЛЕНИЕ 2:
В ответ на комментарий приведена дополнительная информация о том, как я обрабатываю состояние с использованием приставки.
Для моего фидавкладка (список сообщений), файл действий:
import firebase from 'firebase';
import _ from 'lodash';
import {
POST_CHANGED,
SEND_BUTTON_PRESSED,
POST_SUCCESS,
REQUEST_FEED_DATA,
REQUEST_FEED_DATA_SUCCESS
} from '../constants/Types';
export const postChanged = (text) => {
return {
type: POST_CHANGED,
payload: text
};
};
export const sendButtonPressed = (postContent, firstName, lastName, rank, organization) => {
if (postContent) {
return (dispatch) => {
dispatch({ type: SEND_BUTTON_PRESSED });
const name = `${firstName} ${lastName}`;
const time = new Date().toLocaleString();
const comments = 0;
firebase.database().ref(`${organization}/posts`)
.push({ name, rank, time, comments, postContent })
.then(dispatch({ type: POST_SUCCESS }));
};
} return { type: '' };
};
export const fetchFeed = (organization) => {
return (dispatch) => {
dispatch({ type: REQUEST_FEED_DATA });
firebase.database().ref(`${organization}/posts`)
.on('value', snapshot => {
const array = _.map(snapshot.val(), (val) => {
return { ...val };
});
const feed = array.reverse();
dispatch({ type: REQUEST_FEED_DATA_SUCCESS, payload: feed });
});
};
};
и соответствующий файл редуктора:
import {
POST_CHANGED,
SEND_BUTTON_PRESSED,
POST_SUCCESS,
REQUEST_FEED_DATA,
REQUEST_FEED_DATA_SUCCESS
} from '../constants/Types';
const INITIAL_STATE = {
postContent: '',
posting: false,
loadingList: true,
feedData: []
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case POST_CHANGED:
return { ...state, postContent: action.payload };
case SEND_BUTTON_PRESSED:
return { ...state, posting: true };
case POST_SUCCESS:
return { ...state, posting: false, postContent: '' };
case REQUEST_FEED_DATA:
return { ...state, loadingList: true };
case REQUEST_FEED_DATA_SUCCESS:
return { ...state, feedData: action.payload, loadingList: false };
default:
return { state };
}
};
Для вкладки моих пользователей (список пользователей), файл действийэто:
import firebase from 'firebase';
import _ from 'lodash';
import {
REQUEST_LIST_DATA,
REQUEST_LIST_DATA_SUCCESS,
REQUEST_LIST_DATA_FAILED,
FETCH_SELECTED_PROFILE,
FETCH_SELECTED_PROFILE_SUCCESS
} from '../constants/Types';
export const fetchActivesList = (organization) => {
return (dispatch) => {
dispatch({ type: REQUEST_LIST_DATA });
firebase.database().ref(`${organization}/activesList`)
.on('value', snapshot => {
const activesList = _.map(snapshot.val(), (val, rank) => {
return { ...val, rank };
});
dispatch({ type: REQUEST_LIST_DATA_SUCCESS, payload: activesList });
});
};
};
export const fetchSelectedProfile = (organization, rank) => {
return (dispatch) => {
dispatch({ type: FETCH_SELECTED_PROFILE });
firebase.database().ref(`${organization}/profiles/${rank}`)
.on('value', snapshot => {
dispatch({ type: FETCH_SELECTED_PROFILE_SUCCESS, payload: snapshot.val() });
});
};
};
И соответствующий файл редуктора:
import {
REQUEST_LIST_DATA,
REQUEST_LIST_DATA_SUCCESS,
REQUEST_LIST_DATA_FAILED,
FETCH_SELECTED_PROFILE,
FETCH_SELECTED_PROFILE_SUCCESS
} from '../constants/Types';
const INITIAL_STATE = {
loadingList: false,
loadingProfile: false,
error: '',
listData: [],
//selectedProfileStats
selectedAdmin: false,
selectedBrotherhoods: 0,
selectedChapters: 0,
selectedCommunityService: 0,
selectedDues: 0,
selectedFirstName: '',
selectedLastName: '',
selectedMixers: 0,
selectedPosition: '',
selectedOrganization: '',
selectedRank: '',
selectedGoodStanding: true,
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case REQUEST_LIST_DATA:
return { ...state, loadingList: true };
case REQUEST_LIST_DATA_SUCCESS:
return { ...state, listData: action.payload, loadingList: false, error: '' };
case REQUEST_LIST_DATA_FAILED:
return { ...state, error: action.payload, loadingList: false };
case FETCH_SELECTED_PROFILE:
return { ...state, loadingProfile: true };
case FETCH_SELECTED_PROFILE_SUCCESS:
return {
...state,
loadingProfile: false,
selectedAdmin: action.payload.admin,
selectedBrotherhoods: action.payload.brotherhoods,
selectedChapters: action.payload.chapters,
selectedCommunityService: action.payload.communityService,
selectedDues: action.payload.dues,
selectedFirstName: action.payload.firstName,
selectedLastName: action.payload.lastName,
selectedMixers: action.payload.mixers,
selectedPosition: action.payload.position,
selectedGoodStanding: action.payload.goodStanding,
selectedRank: action.payload.rank
};
default:
return state;
}
};
Я управляю навигацией с помощью библиотеки «response-navigation».Этот код распределен по двум файлам, один из которых представляет собой навигатор-переключатель под названием «AppNavigator.js» и выглядит следующим образом:
import { createSwitchNavigator, createStackNavigator } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
import LoginScreen from '../screens/auth/LoginScreen';
import RegisterChapterScreen from '../screens/auth/RegisterChapterScreen';
import JoinChapterScreen from '../screens/auth/JoinChapterScreen';
const AuthStack = createStackNavigator(
{
Login: LoginScreen,
RegChapter: RegisterChapterScreen,
joinChapter: JoinChapterScreen
},
{
initialRouteName: 'Login'
}
);
export default createSwitchNavigator(
{
// You could add another route here for authentication.
// Read more at https://reactnavigation.org/docs/en/auth-flow.html
Auth: AuthStack,
Main: MainTabNavigator
},
{
initialRouteName: 'Auth'
}
);
Второй файл представляет собой навигатор с вкладками под названием «MainTabNavigator» и выглядит следующим образом:
import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation';
import TabBarIcon from '../components/TabBarIcon';
import FeedScreen from '../screens/feedTab/FeedScreen';
import EventsScreen from '../screens/eventsTab/EventsScreen';
import CreateEventScreen from '../screens/eventsTab/CreateEventScreen';
import ActivesScreen from '../screens/activesTab/ActivesScreen';
import ProfileScreen from '../screens/activesTab/ProfileScreen';
//Feed Tab Navigation Setup
const FeedStack = createStackNavigator({
Feed: FeedScreen,
});
FeedStack.navigationOptions = {
tabBarLabel: 'Feed',
tabBarIcon: ({ focused, tintColor }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-paper${focused ? '' : '-outline'}` : 'md-paper'}
color={tintColor}
/>
),
};
//Events Tab Navigation Setup
const EventsStack = createStackNavigator({
EventsList: EventsScreen,
CreateEvent: CreateEventScreen
});
EventsStack.navigationOptions = {
tabBarLabel: 'Events',
tabBarIcon: ({ focused, tintColor }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-person${focused ? '' : '-outline'}` : 'md-person'}
color={tintColor}
/>
),
};
//Actives Tab Navigation Setup
const ActivesStack = createStackNavigator({
Actives: ActivesScreen,
SelectedProfile: ProfileScreen,
});
ActivesStack.navigationOptions = {
tabBarLabel: 'Actives',
tabBarIcon: ({ focused, tintColor }) => (
<TabBarIcon
focused={focused}
name={Platform.OS === 'ios' ? `ios-contacts${focused ? '' : '-outline'}` : 'md-contacts'}
color={tintColor}
/>
),
};
export default createBottomTabNavigator(
{
ActivesStack,
FeedStack,
EventsStack,
},
{
tabBarOptions: {
activeTintColor: 'red',
inactiveTintColor: 'gray',
}
}
);
Надеюсь, это достаточно информации, но, пожалуйста, прокомментируйте, если вам нужно увидеть другие части моего кода.
Спасибо