2016-06-20 10 views
1

Ich bin neu zu reagieren-redux.Ich muss sagen, ich lese viel Beispielprojekt, viele verwenden Webpack und paar viel Paket zusammen ohne detaillierte Einführung. Ich lese auch offizielle Beispiel mehrmals, aber ich kann es immer noch nicht gut verstehen, besonders in how to get initial data, and show it in the dom und communicate with ajax (nicht wie jquery.ajax, verwenden Sie Ajax in Redux scheint sehr komplex, jeder Code hat unterschiedliche Ansatz und anderen Stil machen es sehr schwer zu verstehen)react-redux initial ajax data und generieren childrens

Ich entscheide mich, einen Dateimanager Webui zu bauen, um react-redux zu lernen. Zunächst, ich will es nur funktionieren, so dass keine Ajax:

Container/App.js:

import React, { Component, PropTypes } from 'react'; 
import { bindActionCreators } from 'redux'; 
import { connect } from 'react-redux'; 
import {getFileList} from '../actions/NodeActions' 
import Footer from '../components/Footer'; 
import TreeNode from '../containers/TreeNode'; 
import Home from '../containers/Home'; 


export default class App extends Component { 

    componentDidMount() { 
    let nodes = getFileList(); 
    this.setState({ 
     nodes: nodes 
    }); 
    } 

    render() { 
    const { actions } = this.props; 
    const { nodes } = this.state; 
    return (
     <div className="main-app-container"> 
     <Home /> 
     <div className="main-app-nav">Simple Redux Boilerplate</div> 
     {nodes.map(node => 
      <TreeNode key={node.name} node={node} {...actions} /> 
     )} 
     <Footer /> 
     </div> 
    ); 
    } 
} 

function mapStateToProps(state) { 
    return { 
    test: state.test 
    }; 
} 


function mapDispatchToProps(dispatch) { 
    return { 
    actions: bindActionCreators(getFileList, dispatch) 
    }; 
} 

export default connect(
    mapStateToProps, 
    mapDispatchToProps 
)(App); 

Aktionen/NodeActions.js:

import { OPEN_NODE, CLOSE_NODE } from '../constants/ActionTypes'; 

export function openNode() { 
    return { 
    type: OPEN_NODE 
    }; 
} 

export function closeNode() { 
    return { 
    type: CLOSE_NODE 
    }; 
} 

class NodeModel { 
    constructor(name, path, type, right) { 
     this.name = name; 
     this.path = path; 
     this.type = type; 
     this.right = right; 
    } 
} 

const testNodes = [ 
    new NodeModel('t1','t1', 'd', '777'), 
    new NodeModel('t2','t2', 'd', '447'), 
    new NodeModel('t3','t3', 'd', '667'), 
] 

export function getFileList() { 
    return { 
    nodes: testNodes 
    } 
} 

export function ansyncGetFileList() { 
    return dispatch => { 
    setTimeout(() => { 
     dispatch(getFileList()); 
    }, 1000); 
    }; 
} 

Minderer/index.js

import { combineReducers } from 'redux'; 
import opener from './TreeNodeReducer' 

const rootReducer = combineReducers({ 
    opener 
}); 

export default rootReducer; 

Minderer/TreeNodeReducer.js

import { OPEN_NODE, CLOSE_NODE } from '../constants/ActionTypes'; 

const initialState = [ 
    { 
    open: false 
    } 
] 

export default function opener(state = initialState, action) { 
    switch (action.type) { 
    case OPEN_NODE: 
    return true; 
    case CLOSE_NODE: 
    return false; 
    default: 
    return state; 
    } 
} 

Reduzierungen/index.js

import { combineReducers } from 'redux'; 
import opener from './TreeNodeReducer' 

const rootReducer = combineReducers({ 
    opener 
}); 

export default rootReducer; 

store/store.js (eine Kopie von einer redux Demo):

import { createStore, applyMiddleware, compose } from 'redux'; 
import rootReducer from '../reducers'; 
import createLogger from 'redux-logger'; 
import thunk from 'redux-thunk'; 
import DevTools from '../containers/DevTools'; 

const logger = createLogger(); 

const finalCreateStore = compose(
    // Middleware you want to use in development: 
    applyMiddleware(logger, thunk), 
    // Required! Enable Redux DevTools with the monitors you chose 
    DevTools.instrument() 
)(createStore); 

module.exports = function configureStore(initialState) { 
    const store = finalCreateStore(rootReducer, initialState); 

    // Hot reload reducers (requires Webpack or Browserify HMR to be enabled) 
    if (module.hot) { 
    module.hot.accept('../reducers',() => 
     store.replaceReducer(require('../reducers')) 
    ); 
    } 

    return store; 
}; 

Chromkonsole sagt: Uncaught TypeError: Cannot read property 'nodes' of null bei App render() {

Ich kenne die es6 nicht gut, aufgrund der seltsamen Syntax redude-redux lese mich das es6 doc, aber ich bin nicht sicher, ob mein Code richtig ist.

Tring:

  1. denke ich, vielleicht nicht testNodes mit new Instanz in der Liste erstellen, so dass ich ändern testNodes auf Ebene json: const testNodes = [ {name:'t1',type:'t1'}, {name:'t2',type:'t2'}, {name:'t3',type:'t3'}, ] Noch gleichen Fehler

  2. vielleicht Aktion kann nicht Holen Sie sich die globale testNodes? Ich bewege mich testNodes in getFileList, funktioniert auch nicht.

Ich habe keine Ahnung. Nachdem ich das gelöst habe, würde ich versuchen, getFileList Inhalt zu einem Ajax-Aufruf zu ersetzen.

PS: Meine react-Route haben auch seltsames Problem, Chrom zeigen leere Seite und kein Fehler, wenn ich App mit Route wrap, fühle mich einfach react-redux ist so schwer für newbee ... das ist nur einige beschweren ...

+0

können Sie uns zeigen, wie Sie Shop mit Wurzelreduzierer konfiguriert haben? –

+0

@ code-jaff Ich denke, Laden und Reduzierer ist nicht viel zu dieser Frage beziehen, also nicht sie, um eine neue Sicht zu machen. Jetzt füge ich den Code zur Frage hinzu. – Mithril

Antwort

3

einfach

  1. Sie brauchen sich nicht zu bindActionCreators selbst
  2. Sie this.props.getFileList
  3. Sie es Staates mit Komponente verwalten müssen nicht verwenden müssen

für zB.

import {ansyncGetFileList} from '../actions/NodeActions' 

componentWillMount() { 
    // this will update the nodes on state 
    this.props.getFileList(); 
} 

render() { 
    // will be re-rendered once store updated 
    const {nodes} = this.props; 
    // use nodes 
} 

function mapStateToProps(state) { 
    return { 
    nodes: state.nodes 
    }; 
} 

export default connect(
    mapStateToProps, 
    { getFileList: ansyncGetFileList } 
)(App); 

Great Example

-Update auf die Frage Update basiert und kommentieren

  1. seit Ihrem Zustand Baum für Knoten keine Karte haben Sie es in der staatlichen haben müssen Wurzel oder opener Unterbaum.
  2. für async Betrieb müssen Sie Ihre Thunk Aktion Creator für ändern.

    export function ansyncGetFileList() { 
        return dispatch => { 
        setTimeout(() => { 
         dispatch({ type: 'NODES_SUCCESS', nodes: getFileList()}); // might need to export the type as constant 
        }, 1000); 
        }; 
    } 
    
  3. Griff der NODES_SUCCESS Aktionstyp in Minderer

    const initialState = { 
        nodes: [] 
    }; 
    export default function nodes(state = initialState, action) { 
        switch (action.type) { 
        // ... 
        case 'NODES_SUCCESS': 
        let nodes = state.nodes.slice(); 
        return nodes.concat(action.nodes); 
        // ... 
        } 
    } 
    
  4. Verwendung Knoten reducer Knoten Unterstruktur für zB zu verwalten.

    import { combineReducers } from 'redux'; 
    import opener from './TreeNodeReducer' 
    import nodes from './nodes' 
    
    const rootReducer = combineReducers({ 
        opener, nodes 
    }); 
    
    export default rootReducer; 
    
  5. Verwendung mapStateToProps wie oben die Knoten für bindActionCreators

  6. bezüglich mapDispatchToProps

    Der einzige Anwendungsfall zu erhalten ist, wenn Sie einige Aktion Schöpfer auf eine Komponente übergeben wollen, die isn Ich kenne Redux nicht, und Sie möchten den Versand oder den Redux-Speicher nicht weiterleiten.

    Da Sie bereits Zugriff auf dispatch haben, können Sie direkt anrufen. Das Übergeben einer Karte ist eine Kurzversion davon. video

+0

Vielen Dank, ich hätte nie gedacht, dass 'this.props.getFileList();' nur meinen Zweck erfüllen würde! Aber warum brauche ich keine "bindActionCreators"? Ich sehe eine Menge Beispiele dafür, und einige von ihnen liefern die Aktionen an den Kind-Knoten. – Mithril

+0

Oh, ich verstehe, 'getFileList' in meinem Code ist kein' ActionCreater', also keine Notwendigkeit zu binden. – Mithril

+0

@mithril aktualisierte Antwort, bitte überprüfen Sie es –