Компоненты, представленные в FlatList, переопределяются, даже если они объявлены как PureComponent, а ссылки на их реквизиты не были изменены. - PullRequest
1 голос
/ 10 июля 2019

Я работаю над собственным встроенным приложением с избыточностью, в котором я извлекаю посты, поскольку на страницах каждой страницы содержится 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, я ожидаю, что существующие записи имеют одинаковую ссылку в предыдущем и новом массиве записей, поэтому они не должны перерисовываться.

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Похоже, вам нужно добавить key к вашим Post с:

<Post 
    key = {item.id}                        
    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 ) }
 />

Теперь React может сказать, какие предметы новые, а какие были ранее.

0 голосов
/ 10 июля 2019

, если вы используете FlatList для рендеринга динамических или разбитых на страницы данных из REST API, вы не должны использовать FlatList в качестве PureComponent. PureComponent не должен иметь состояния, и поэтому весь компонент будет повторно визуализироваться при изменении реквизита. Вы можете использовать Post в качестве PureComponent, но не весь FlatList здесь. Попробуйте и не используйте FlatList в качестве PureComponent. Используйте Post как PureComponent с Компонентом Key как key = {postitem.id}.

Когда Компонент используется как чистый компонент, он не удерживает никакого состояния, и здесь в вашем случае FlatList - это PureComponent, поэтому, как только данные изменяются, он вызывает функцию рендеринга для этого FlatList и полностью повторно rendred.

...