簡體   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