这是BookList
属性更改中要重新呈现的filter.sortBy
组件。
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
的值。根据{{1}}上方mapStateToProps()
内部记录的内容,正确进行了更改。
更改state.filter.sortBy
的值后,如何重新渲染BookList
?
完整的仓库位于https://github.com/ElAnonimo/booklist
到目前为止,我已经在sortBy
中尝试过constructor()
和componentWillReceiveProps()
。
更新。
这是我的BookList
选择器的样子
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
组件。导致Redux的道具没有变化。
这就是我如何返回原始数组的修改后的副本。
BookList
这归功于Ryan C。
更新2。 还要感谢RyanC。感谢您分享智慧。
这是他建议的修改方法。
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;
}
});
};
。在缺少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
这些更改实际上消除了项目中对选择器的需求。
答案 0 :(得分:2)
我怀疑您的sortBooks
方法正在对数组进行排序,从而始终返回相同的books
数组引用(即使其中的元素顺序可能已更改)。这导致react-redux认为mapStateToProps
返回的属性没有更改(react-redux仅做一个浅表比较)。如果您将sortBooks
更改为首先复制该数组,然后对其进行排序并返回新数组,而不是对现有数组进行突变,那么它将起作用。
更新 看到您的解决方案后,我认为最好在化简器中进行这种排序,因为books数组处于状态。这样,您只能控制响应于更改排序的操作进行排序。现在,由于mapStateToProps 总是返回一个不同的books数组,因此每次状态更改(即使排序没有改变)时,您最终都将重新呈现书单。