2016-03-15 34 views
8

Thử React + Redux, và có thể đang làm điều gì đó rõ ràng là ngu ngốc, vì một thành phần kích hoạt một hành động tìm nạp dữ liệu qua mạng không được cập nhật (kết xuất lại) khi dữ liệu được tìm nạp.React + Redux: Thành phần không cập nhật

Dưới đây là các bit có liên quan của mã của tôi:

Các index.js cấp cao nhất phục vụ như là một điểm khởi đầu cho các ứng dụng:

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')); 

chứa cấp cao nhất App:

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) 

Thành phần kích hoạt tác vụ gửi yêu cầu dữ liệu khi nó sắp được gắn kết và được cho là hiển thị dữ liệu được tìm nạp:

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) 

Action Creator:

import * as types from '../constants/ActionTypes'; 
import axios from 'axios'; 

export function fetchResources() { 
    return { 
    type: types.FETCH_FIRST, 
    payload: axios.get('/sampledata/1.json') 
    } 
} 

Giảm cho lấy hành động:

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 
    } 
}; 

và cuối cùng là giảm root:

import { combineReducers } from 'redux'; 
import navigationReducer from './navigation-reducer'; 
import resourcesReducer from './resources-reducer'; 

const rootReducer = combineReducers({ 
    navigationReducer, 
    resourcesReducer 
}); 

export default rootReducer; 

Vì vậy, đây là những gì tôi đang quan sát. Hành động yêu cầu dữ liệu được kích hoạt thành công, yêu cầu được gửi đi, trình giảm sẽ nhận được yêu cầu đó khi lời hứa được giải quyết và cập nhật trạng thái với dữ liệu được tìm nạp. Tại thời điểm này, tôi mong đợi thành phần App cấp cao nhất và thành phần Showcase để phát hiện rằng cửa hàng đã cập nhật và để hiển thị lại, nhưng tôi không thấy nó trong bảng điều khiển.

Ngoài ra, tôi bối rối bởi redux-logger 's giao diện điều khiển đầu ra:

enter image description here

Cụ thể, tôi ngạc nhiên khi thấy rằng các state chứa gia giảm từ rootReducer - Tôi không biết nếu nó là đúng (một ví dụ trên Redux logger Github page hiển thị trạng thái không có bộ giảm tốc). Nó cũng có vẻ ngạc nhiên khi prev state được báo cáo bởi redux-logger chứa cùng một đối tượng resourcesReducernext state, mặc dù theo trực giác tôi mong đợi prev state ít nhiều trống.

Bạn có thể vui lòng chỉ ra những gì tôi đang làm sai và cách nhận các thành phần React phản hồi lại các thay đổi của state?

============================================== ====

CẬP NHẬT:

1) Thay đổi mapStateToProps chức năng trong thành phần App để nó một cách chính xác bản đồ để giảm trạng thái:

function mapStateToProps(state) { 
    return { 
    resources: state.resourcesReducer 
    } 
} 

2) Tuy nhiên vượt qua resources xuống thành phần `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) Đang cố gắng để hiển thị resources trên màn hình bằng stringifying nó để xem những gì thực sự bên trong đối tượng này:

render() { 
    console.log('resources', this.props); 
    return (
     <div> 
     This is showcase {JSON.stringify(this.props.resources)} 
     </div> 
    ); 
    } 

Xem này trên màn hình: This is showcase {}. Các thành phần dường như không tái render.

Đây là ảnh chụp màn hình của bảng điều khiển cho biết rằng đạo cụ của Ứng dụng đã được cập nhật với các giá trị từ số next state. Tuy nhiên, điều đó không gây ra các thành phần để tái render:

enter image description here

CẬP NHẬT LẠI: Và javascript-fu của tôi rất kém, quá. Tôi đã không hoàn toàn nhận ra rằng bằng cách trở về Object.assign (state, {resources: action.payload.data }); Tôi đã trong thực tế, đột biến nhà nước, và rằng một đảo ngược đơn giản của các đối số sẽ cho tôi đạt được những gì tôi dự định. Nhờ có this discussion trên SO để khai sáng.

+0

bạn đã thử thêm khóa vào đối tượng giảm gốc? 'const rootReducer = combinedReducers ({ điều hướng: navigationReducer, tài nguyên: resourcesReducer });' – anoop

Trả lời

6

Tôi ngạc nhiên khi thấy rằng nhà nước chứa gia giảm từ rootReducer

Đây là cách nó hoạt động. Hãy xem kỹ hơn combineReducers().

const rootReducer = combineReducers({ 
    navigationReducer, 
    resourcesReducer 
}); 

Nhận ra rằng đó không phải là danh sách các thông số; nó là một tham số đối tượng duy nhất. Có lẽ đó là rõ ràng hơn trong cú pháp ES5:

var rootReducer = combineReducers({ 
    navigationReducer: navigationReducer, 
    resourcesReducer: resourcesReducer 
}); 

Các resourcesReducer điểm chìa khóa dẫn đến trạng thái được trả về bởi các resourcesReducer() chức năng. Tức là, biến số state trong số resourcesReducer() chỉ là một phần của toàn bộ tiểu bang.

Các chức năng được chuyển đến connect() lấy toàn bộ trạng thái làm đối số. Diện mạo của bạn thực sự trông như thế nào:

export default connect(state => ({ 
    resources: state.resourcesReducer.resources 
}))(Showcase); 
+0

Cảm ơn bạn. Nhận xét của bạn đã làm rõ hơn mối quan hệ giữa trạng thái và bộ giảm (và combinedReducers) là gì, nhưng ngay cả sau khi tôi cập nhật mã của mình (xem phần CẬP NHẬT trong câu hỏi ban đầu của tôi), bản cập nhật của tiểu bang không dẫn đến hiển thị lại thành phần . Bây giờ tôi chỉ đăng ký thành phần 'App' của mình cho cửa hàng, và đã thay đổi hàm' mapStateToProps' để trả về '{resources: state.resourcesReducer}'.Tôi thấy rằng các cập nhật trạng thái và các đạo cụ 'App' phản ánh thay đổi này, nhưng điều này không làm cho Ứng dụng (hoặc Trình diễn) hiển thị lại. Tôi đang thiếu gì? – azangru

+1

Ok, giờ tôi đã hiểu chuyện gì đang xảy ra. 'Object.assign' của tôi cũng sai. Tôi đã biến đổi trạng thái: 'return Object.assign (state, {resources: action.payload.data})' trong khi những gì tôi thực sự cần làm là trả về một đối tượng mới (ví dụ 'return Object.assign ({resources: action .payload.data}, state) '). Tôi ngớ ngẩn quá. Dường như là một sai lầm phổ biến mặc dù; có một bài rất giống trên SO mà tôi đã bỏ lỡ: http://stackoverflow.com/questions/33140008/react-redux-store-updates-but-react-does-not – azangru

Các vấn đề liên quan