嘗試使用React + Redux,並且可能會做某些顯然很愚蠢的事情,因爲在數據發生時通過網絡觸發操作以獲取數據的組件不會更新(重新呈現)被提取。React + Redux:組件不更新
這裏是我的代碼的相關位:
充當入口點的應用程序中的頂級index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { Router, browserHistory } from 'react-router';
import reduxPromise from 'redux-promise';
import createLogger from 'redux-logger';
const logger = createLogger();
import routes from './routes';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware(reduxPromise, logger)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<Router history={browserHistory} routes={routes} />
</Provider>
, document.querySelector('.container'));
頂層容器應用程序:
import React, {Component} from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions';
import Header from '../components/header';
import Showcase from '../components/showcase';
function mapStateToProps(state) {
return {
resources: state.resources
}
}
function mapDispatchToProps(dispatch) {
return {
fetchResources:() => {
dispatch(Actions.fetchResources());
}
}
}
class App extends Component {
render() {
console.log('props in App', this.props);
return (
<div>
<Header/>
<Showcase
fetchResources={this.props.fetchResources}
resources={this.props.resources}
/>
</div>
);
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(App)
觸發動作的組件,當它要安裝並且應該顯示提取的數據時發送數據請求:
import React, {Component} from 'react';
import {connect} from 'react-redux';
class Showcase extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.fetchResources();
}
render() {
console.log('resources', this.props);
return (
<div>
This is showcase
</div>
);
}
}
export default connect(state => ({resources: state.resources}))(Showcase)
行動者:
import * as types from '../constants/ActionTypes';
import axios from 'axios';
export function fetchResources() {
return {
type: types.FETCH_FIRST,
payload: axios.get('/sampledata/1.json')
}
}
減速的獲取操作:
import * as types from '../constants/ActionTypes';
export default function resourcesReducer (state={}, action) {
switch (action.type) {
case types.FETCH_FIRST:
console.log('about to return', Object.assign (state, {resources: action.payload.data }))
return Object.assign (state, {resources: action.payload.data });
default:
return state
}
};
,最後根減速機:
import { combineReducers } from 'redux';
import navigationReducer from './navigation-reducer';
import resourcesReducer from './resources-reducer';
const rootReducer = combineReducers({
navigationReducer,
resourcesReducer
});
export default rootReducer;
所以,這裏是我所觀察。成功觸發請求數據的操作,發送請求,Reducer在解決承諾時收到請求,並使用獲取的數據更新狀態。此時,我期望頂級App
組件和Showcase
組件檢測到商店已更新並重新渲染,但我在控制檯中看不到它。
而且,我被redux-logger
的控制檯輸出困惑:
具體來說,我奇怪爲什麼地看到,state
包含來自rootReducer減速 - 我不知道這是否是正確的( Redux logger Github page上的示例顯示了沒有縮減器的狀態)。令人驚訝的是,由redux-logger
報告的prev state
包含與next state
相同的resourcesReducer
對象,儘管直觀地我期望prev state
或多或少是空的。
請你指出我做錯了什麼,以及如何讓React組件響應state
更改?
============================================== ====
更新:
1)在App
部件改變了mapStateToProps
功能,使得它正確地映射到減速機狀態:
function mapStateToProps(state) {
return {
resources: state.resourcesReducer
}
}
2)靜止傳遞resources
下降到'Showcase組件:
render() {
console.log('props in App', this.props);
return (
<div>
<Header navigateActions={this.props.navigateActions}/>
React simple starter
<Showcase
fetchResources={this.props.fetchResources}
resources={this.props.resources}
/>
</div>
);
3)試圖通過字符串化它,看看有什麼實際上是這個對象內部,以顯示在屏幕上resources
:
render() {
console.log('resources', this.props);
return (
<div>
This is showcase {JSON.stringify(this.props.resources)}
</div>
);
}
看到這個屏幕上:This is showcase {}
。該組件似乎不會重新渲染。
下面是控制檯的屏幕截圖,顯示App的道具已經更新了next state
的值。不過,這並沒有導致組件重新渲染:
再次更新:而我的JavaScript富窮了。我並不完全意識到,通過返回Object.assign (state, {resources: action.payload.data });
我實際上是在顛覆國家,而且一個簡單的論證倒置可以讓我達到我的目的。感謝this discussion對SO的啓發。
你是否嘗試向root reducer對象添加密鑰? 'const rootReducer = combineReducers({navigation:navigationReducer, resources:resourcesReducer });' – anoop