持久值不会影响链下的代码

Persisted value won't affect the code down the chain

这是 filterAction 向持久化减速器发出值的操作。在组件的下拉列表中使用 dispatch() 调用此操作。

import { SORT_BY_TITLE, SORT_BY_RELEASED_AT } from './types';

// sort by title
export const sortByTitle = () => ({
  type: SORT_BY_TITLE
});

// sort by released at
export const sortByReleasedAt = () => ({
  type: SORT_BY_RELEASED_AT
});

对应filterReducer

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

const initialState = {
  sortBy: 'title'
};

export default function(state = initialState, action) {
  switch(action.type) {
    case SORT_BY_TITLE:
      return {
        ...state,
        sortBy: 'title'
      };
    case SORT_BY_RELEASED_AT:
      return {
        ...state,
        sortBy: 'releasedAt'
      };
    default:
      return state;
  }
};

filterReducer值是主组合reducer中持久化的

export default combineReducers({
  books: booksReducer,
  book: bookReducer,
  form: addBookFormReducer,
  filter: filterReducer
});

应用的store

import { createStore, applyMiddleware } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

const middleware = [thunk];

const persistConfig = {
    key: 'root',
    storage,
    whitelist: ['filter']
};

const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(persistedReducer, {}, applyMiddleware(...middleware));
export const persistor = persistStore(store);

在主减速器的 filter 部分保留的值显示在下拉列表更改中,在该下拉列表中调用 filterActiondispatch()

这是创建应用 storebooks 部分的 booksReducer,因此 books 显示在组件中。

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

const initialState = {
  books: [],
  loading: false
};

const booksReducer = (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;
  }
};

export default booksReducer;

主减速器的 filter 部分在页面重新加载时仍然存在,但是 books 列表默认按标题排序显示。

如何让应用程序在页面重新加载时保持排序?完整的回购在 https://github.com/ElAnonimo/booklister

BookList 上加载 getBooks() 操作 return 将已排序的书籍列表重置为默认排序,这样更容易只保留 filter 属性store 然后在每次加载 BookList 组件时对 books 列表进行排序。

已进行更改

booksReducer

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

const initialState = {
  books: [],
    loading: false
};

const booksReducer = (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)]
      };
    default:
      return state;
  }
};

export default booksReducer;

BookList

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

  applySorting(books) {
    const sortBy = this.props.filter.sortBy;

    if (!sortBy) {
        return books;
        }

        return books.sort((a, b) => a[sortBy] < b[sortBy] ? -1 : 1);
    }

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

    let booksContent;

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