繁体   English   中英

React / Redux:状态在Redux对象中更新,但是React组件不会重新渲染

[英]React/Redux: State is updated in Redux object, but React component doesn't re-render

试图浏览相似的问题,但没有找到相似的问题。

我正在尝试在应用中按名称和数量实现排序,此事件在此组件中触发:

 import React, { Component } from 'react'; import { connect } from 'react-redux'; import { sortByExpenseName, sortByExpenseAmount } from '../actions/expensesFilters'; class ExpensesListFilter extends Component { onSortByExpenseName = () => { this.props.sortByExpenseName(); }; onSortByExpenseAmount = () => { this.props.sortByExpenseAmount(); } render() { return ( <div> <span>Expense Name</span> <button onClick={this.onSortByExpenseName}>Sort me by name</button> <button onClick={this.onSortByExpenseAmount}>Sort me by amount</button> </div> ) } } const mapDispatchToProps = (dispatch) => ({ sortByExpenseName: () => dispatch(sortByExpenseName()), sortByExpenseAmount: () => dispatch(sortByExpenseAmount()), }); export default connect(null, mapDispatchToProps)(ExpensesListFilter); 

为此,我正在使用以下选择器:

 export default (expenses, { sortBy }) => { return expenses.sort((a, b) => { if (sortBy === 'name') { return a.name < b.name ? 1 : -1; } else if (sortBy === 'amount') { return parseInt(a.amount, 10) < parseInt(b.amount, 10) ? 1 : -1; } }); }; 

我在mapStateToProps函数中为ExpensesList组件运行此选择器:

 import React from 'react'; import { connect } from 'react-redux'; import ExpensesItem from './ExpensesItem'; // my selector import sortExpenses from '../selectors/sortExpenses'; const ExpensesList = props => ( <div className="content-container"> {props.expenses && props.expenses.map((expense) => { return <ExpensesItem key={expense.id} {...expense} />; }) } </div> ); // Here I run my selector to sort expenses const mapStateToProps = (state) => { return { expenses: sortExpenses(state.expensesData.expenses, state.expensesFilters), }; }; export default connect(mapStateToProps)(ExpensesList); 

此选择器更新了我的过滤器缩减器,这导致我的应用程序状态更新:

 import { SORT_BY_EXPENSE_NAME, SORT_BY_EXPENSE_AMOUNT } from '../actions/types'; const INITIAL_EXPENSE_FILTER_STATE = { sortBy: 'name', }; export default (state = INITIAL_EXPENSE_FILTER_STATE, action) => { switch (action.type) { case SORT_BY_EXPENSE_NAME: return { ...state, sortBy: 'name', }; case SORT_BY_EXPENSE_AMOUNT: return { ...state, sortBy: 'amount', }; default: return state; } }; 

排序事件导致我的状态更新,下面的我的费用减少器中的费用数组已更新,并通过选择器进行了排序,但在我的费用数组更新后,ExpensesList组件不会重新呈现。 我希望ExpensesList组件执行的操作是使用已排序的费用数组重新渲染并在列表中对ExpensesItem组件进行排序。 失败的原因可能是什么? 可以肯定的是,我错过了一些必不可少的东西,但无法弄清楚是什么。 我的费用减少者:

 import { FETCH_EXPENSES } from '../actions/types'; const INITIAL_STATE = {}; export default (state = INITIAL_STATE, action) => { switch (action.type) { case FETCH_EXPENSES: return { ...state, expenses: action.expenses.data, }; default: return state; } }; 

所有这些组件都是此父组件的子代:

 import React from 'react'; import ExpensesListFilter from './ExpensesListFilter'; import ExpensesList from './ExpensesList'; const MainPage = () => ( <div className="box-layout"> <div className="box-layout__box"> <ExpensesListFilter /> <ExpensesList /> </div> </div> ); export default MainPage; 

App.js文件(我在其中运行startExpenseFetch)

 import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import 'normalize.css/normalize.css'; import AppRouter, { history } from './routers/AppRouter'; import configureStore from './store/configureStore'; import LoadingPage from './components/LoadingPage'; import { startExpenseFetch } from './actions/expensesData'; import './styles/styles.scss'; const store = configureStore(); const jsx = ( <Provider store={store}> <AppRouter /> </Provider> ); let hasRendered = false; const renderApp = () => { if (!hasRendered) { ReactDOM.render(jsx, document.getElementById('app')); hasRendered = true; } }; store.dispatch(startExpenseFetch()).then(() => { renderApp(); }); ReactDOM.render(<LoadingPage />, document.getElementById('app')); 

其余文件:

ExpenseItem组件:

 import React from 'react'; const ExpenseItem = ({ amount, name }) => ( <div> <span>{name}</span> <span>{amount}</span> </div> ); export default ExpenseItem; 

动作创作者:

experienceData.js

 import axios from 'axios'; import { FETCH_EXPENSE } from './types'; // no errors here const ROOT_URL = ''; export const fetchExpenseData = expenses => ({ type: FETCH_EXPENSE, expenses, }); export const startExpenseFetch = () => { return (dispatch) => { return axios({ method: 'get', url: `${ROOT_URL}`, }) .then((response) => { dispatch(fetchExpenseData(response)); console.log(response); }) .catch((error) => { console.log(error); }); }; }; 

experienceFilters.js

 import { SORT_BY_EXPENSE_NAME, SORT_BY_EXPENSE_AMOUNT } from './types'; export const sortByExpenseName = () => ({ type: SORT_BY_EXPENSE_NAME, }); export const sortByExpenseAmount = () => ({ type: SORT_BY_EXPENSE_AMOUNT, }); 

configureStores.js文件

 import { createStore, combineReducers, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import expensesDataReducer from '../reducers/expensesData'; import expensesFilterReducer from '../reducers/expensesFilters'; const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; export default () => { const store = createStore( combineReducers({ expensesData: expensesDataReducer, expensesFilters: expensesFilterReducer, }), composeEnhancers(applyMiddleware(thunk)) ); return store; }; 

AppRouter.js文件

 import React from 'react'; import { Router, Route, Switch, Link, NavLink } from 'react-router-dom'; import createHistory from 'history/createBrowserHistory'; import MainPage from '../components/MainPage'; import NotFoundPage from '../components/NotFoundPage'; export const history = createHistory(); const AppRouter = () => ( <Router history={history}> <div> <Switch> <Route path="/" component={MainPage} exact={true} /> <Route component={NotFoundPage} /> </Switch> </div> </Router> ); export default AppRouter; 

您拨打选择器时没有打错字吗? :)

// Here I run my selector to sort expenses
const mapStateToProps = (state) => {
  return {
    expenses: sortExpenses(state.expensesData.expenses, state.expnsesFilters),
  };
};

state.expnsesFilters看起来应该是状态。 费用过滤器

这是您应让sortExpenses选择器自行获取所需状态的一部分并自行完成工作的原因之一。 您可以对其进行隔离测试,并避免出现此类错误。

我发现了发生这种情况的原因,在选择器中,我正在改变应用程序的状态。 我没有从中返回新的数组,而是在改变旧的数组,这并没有触发我的vue层重新渲染。 修复了它,现在可以使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM