[英]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_TITLE
和SORT_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.