簡體   English   中英

React組件不會在道具變更時重新渲染

[英]React component won't re-render on props change

這是要在filter.sortBy屬性更改時重新呈現的BookList組件。

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { getBooks } from '../actions/bookActions';
import Spinner from './Spinner';
import BookItem from './BookItem';
import sortBooks from '../selectors/books';

class BookList extends Component {
  componentDidMount() {
    this.props.getBooks();
  }

  render() {
    const { books, loading } = this.props;

    let booksContent;

    if (!books || loading) {
      booksContent = <Spinner />;
    } else {
      if (books.length > 0) {
        booksContent = books.map(book => <BookItem book={book} key={book._id} />);
      } else {
        booksContent = <h4>No books found</h4>;
      }
    }

    return (
      <div className='feed'>
                <div className='container'>
                    <div className='row'>
                        <div className='col-md-12'>
                            {booksContent}
                        </div>
                    </div>
                </div>
            </div>
    );
  }
}

BookList.propTypes = {
  books: PropTypes.oneOfType([PropTypes.array, PropTypes.object]).isRequired,
  getBooks: PropTypes.func.isRequired
};

const mapStateToProps = (state) => {
  const books = sortBooks(state.books.books, state.filter.sortBy);

  return {
    books: books
  }
};

export default connect(mapStateToProps, { getBooks })(BookList);

還有另一個組件可以更改state.filter.sortBy值。 mapStateToProps()以上的state.filter.sortBy mapStateToProps()內部記錄的內容正確更改。

更改sortBy值時如何重新呈現BookList 完整的倉庫位於https://github.com/ElAnonimo/booklist到目前為止,我已經在BookList嘗試了一個BookList constructor() ,一個componentWillReceiveProps()

更新。

這就是我的sortBooks選擇器的樣子

export default (books, sortBy) => {
  return books
    .sort((a, b) => {
      if (sortBy === 'title') {
        return a.title < b.title ? -1 : 1;
      } else if (sortBy === 'releasedAt') {
        return a.releasedAt < b.releasedAt ? -1 : 1;
      }
    });
};

就像在接受的答案中提到的那樣,選擇器將內部修改的但仍是原始books數組返回給BookList組件。 導致Redux的道具沒有變化。

這就是我如何返回原始數組的修改后的副本。

export default (books, sortBy) => {
  return [...books]
    .sort((a, b) => {
      if (sortBy === 'title') {
        return a.title < b.title ? -1 : 1;
      } else if (sortBy === 'releasedAt') {
        return a.releasedAt < b.releasedAt ? -1 : 1;
      }
    });
};

歸功於RyanC。

更新2.感謝RyanC。謝謝您的分享。

這是他建議的修改方法。

booksReducer 之前缺少SORT_BY_TITLESORT_BY_RELEASED_AT案例。

import {
  GET_BOOKS,
  BOOKS_LOADING,
  DELETE_BOOK,
  SORT_BY_TITLE,
  SORT_BY_RELEASED_AT
} from '../actions/types';

const initialState = {
  books: []
};

export default function(state = initialState, action) {
  switch(action.type) {
    case BOOKS_LOADING:
      return {
        ...state,
        loading: true
      };
    case GET_BOOKS:
      return {
        ...state,
        books: action.payload,
        loading: false
      };
    case DELETE_BOOK:
      return {
        books: [...state.books.filter(book => book._id !== action.payload.id)]
      };
    case SORT_BY_TITLE:
      return {
        ...state,
        books: [...state.books.sort((a, b) => a.title < b.title ? -1 : 1 )]
      };            
    case SORT_BY_RELEASED_AT:
      return {
        ...state,
        books: [...state.books.sort((a, b) => a.releasedAt < b.releasedAt ? -1 : 1 )]
      };    
    default:
      return state;
  }
}

BookList的修改

const mapStateToProps = (state) => ({
    books: state.books.books
});

這些更改實際上消除了項目中選擇器的需要。

我懷疑您的sortBooks方法對數組進行了排序,因此始終返回相同的books數組引用(即使其中的元素順序可能已更改)。 這導致react-redux認為mapStateToProps返回的屬性未更改(react-redux僅進行淺表比較)。 如果您將sortBooks更改為首先復制數組,然后對其進行排序並返回新數組,而不是對現有數組進行突變,則它應該可以工作。

更新在看到您的解決方案之后,我認為最好在化簡器中處理這種排序,因為books數組處於狀態。 這樣,您只能控制響應於更改排序的操作進行排序。 現在的樣子,由於mapStateToProps 總是會返回一個不同的books數組,因此您將在每次狀態更改(即使排序未更改)時重新呈現書單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM