Я работаю над собственным встроенным приложением с избыточностью, в котором я извлекаю посты, поскольку на страницах каждой страницы содержится 5 постов, и они отображаются в FlatList. Когда отображается главный экран, я выбираю первую страницу постов и объединяю их с изначально пустым массивом постов в хранилище. Когда пользователь прокручивает страницу вниз, я иду и извлекаю следующую страницу постов и объединяю их с массивом постов. Проблема заключается в том, что при извлечении следующей страницы постов и их объединении с существующим массивом постов я замечаю, что существующие посты с предыдущих страниц, которые уже отрисованы в FlatList, перерисовываются. Я обнаружил это при входе в метод жизненного цикла componentDidUpdate.
Вот как я отображаю сообщения FlatList на главном экране:
renderPostsList = () => {
const { posts, onFetchPosts, postsComments } = this.props;
return(
<FlatList
style = { styles.postsList }
keyExtractor = { item => item.id.toString() }
onEndReachedThreshold = { 0.5 }
onEndReached = { ({distanceFromEnd}) => { onFetchPosts() } }
data = { posts }
renderItem = { ({ item }) => {
return(
<Post
userName = { item.user.username }
time = { item.created_at }
content = { item.onlyText }
commentsCount = { item.commentCount }
likesCount = { item.likeCount }
dislikesCount = { item.dislikeCount }
sharesCount = { item.shareCount }
comments = { postsComments.get( item.id ) }
fetchCommentsHandler = { this.getFetchCommentsHandlerForPost( item ) }
/>
);
}
}
/>
);
};
Вот метод getFetchCommentsHandlerForPost
:
getFetchCommentsHandlerForPost = post => {
return () => {
if ( post.commentCount > 0 ) {
this.props.onFetchComments( post.id );
}
};
};
Вот onFetchPosts
Создатель действия:
export const fetchPosts = () => ( dispatch, getState ) => {
const { nextPage } = getState().posts;
if ( !nextPage ) {
return;
}
dispatch( startLoading() );
const user = getState().auth.user.user;
const userId = user
? user.id
: null;
axios( '/posts', {
method: 'GET',
params: {
userId,
page: nextPage
}
} )
.then( res => {
const posts = res.data.data.map( item => {
if ( !item.user ) {
item.user = { username: 'No Name' };
}
return item;
} );
dispatch( appendPosts( posts ) );
const { current_page, last_page } = res.data.meta;
const nextPage = current_page === last_page? null : current_page + 1;
dispatch( updateNextPage( nextPage ) );
dispatch( stopLoading() );
} )
.catch( err => {
dispatch( stopLoading() );
dispatch( setError( i18n.t( 'errors.fetch_posts_failed' ) ) )
} );
};
Вот пост редуктора:
import { APPEND_POSTS,
START_LOADING,
STOP_LOADING,
POSTS_SET_ERROR,
POSTS_CLEAR_ERROR,
UPDATE_NEXT_PAGE } from '../actions/ActionTypes';
const initialState = {
posts: [],
nextPage: 1,
isLoading: false,
error: null
};
const postsReducer = ( state = initialState, action ) => {
switch( action.type ) {
case APPEND_POSTS:
return {
...state,
posts: state.posts.concat( action.payload.posts )
};
case UPDATE_NEXT_PAGE:
return {
...state,
nextPage: action.payload.nextPage
};
case START_LOADING:
return {
...state,
isLoading: true
};
case STOP_LOADING:
return {
...state,
isLoading: false
};
case POSTS_SET_ERROR:
return {
...state,
error: action.payload.error
};
case POSTS_CLEAR_ERROR:
return {
...state,
error: null
};
default:
return state;
}
};
export default postsReducer;
Поскольку FlatList и мой Post
компонент PureComponent
, я ожидаю, что существующие записи имеют одинаковую ссылку в предыдущем и новом массиве записей, поэтому они не должны перерисовываться.