2016-06-20 6 views
1

私はreact-redux.Iに新しいです。私は多くのサンプルプロジェクトを読んで、多くのWebpackを使い、私もいくつかの公式の例を読んでいますが、私はまだそれをよく理解できません。特にhow to get initial data, and show it in the domcommunicate with ajax(jquery.ajaxのようなものではありません、reduxでajaxを使うのは非常に複雑です。理解してください)最初のajaxデータを反応させて還元し、子を生成する

私はreact-reduxを学ぶためにファイルマネージャwebuiを構築することにしました。

コンテナ/ 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); 

アクション/ 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); 
    }; 
} 

リデューサー/ index.js

、私はちょうどそれが動作しますので、何のAJAXを開始しないように
import { combineReducers } from 'redux'; 
import opener from './TreeNodeReducer' 

const rootReducer = combineReducers({ 
    opener 
}); 

export default rootReducer; 

還元剤/ 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; 
    } 
} 

リデューサー/ index.js

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

const rootReducer = combineReducers({ 
    opener 
}); 

export default rootReducer; 

店/ store.js(Reduxのデモからコピー):

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

クロームコンソールは言う:App render() {

Uncaught TypeError: Cannot read property 'nodes' of null私はes6をよく知らないのですが、反応が奇妙な構文のために私はes6の文書を読むことができますが、自分のコードが正しいかどうかはわかりません。

トリング:

  1. 私は多分リストにnewインスタンスでtestNodesを作成することはできませんだと思うので、私は無地JSONにtestNodesを変更します。 const testNodes = [ {name:'t1',type:'t1'}, {name:'t2',type:'t2'}, {name:'t3',type:'t3'}, ] まだ同じエラー

  2. 多分アクションはできませんグローバルtestNodesを取得しますか? testNodesgetFileListに移動しても動作しません。

私には分かりません。 これを解決したら、getFileListコンテンツをajax呼び出しに置き換えようとします。

PS:私の反応ルートにも奇妙な問題があります。クロムは空白のページを表示し、エラーはありません。Appを経路に入れても、反応が遅いと感じています...これはちょっと不平です...

+0

ルートレデューサーで店舗をどのように設定しましたか? –

+0

@ code-jaff私はストアとレデューサーはこの質問にはあまり関係がないと思うので、新鮮な見方をするために入れないでください。今私は質問するコードを追加します。 – Mithril

答えて

3

単に

  1. あなた自身bindActionCreatorsへ
  2. を必要としない、あなたは例えばのために、コンポーネントの状態

とそれを管理する必要はありませんthis.props.getFileList

  • を使用する必要があります。

    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

    質問更新に基づいて更新して

    1. コメントあなたの状態のツリーがノードのためのマップを持っていないので、あなたは状態の中で、それを持っている必要がありますルートまたはopenerサブツリー。
    2. async操作では、サンクアクションクリエイター を変更する必要があります。

      export function ansyncGetFileList() { 
          return dispatch => { 
          setTimeout(() => { 
           dispatch({ type: 'NODES_SUCCESS', nodes: getFileList()}); // might need to export the type as constant 
          }, 1000); 
          }; 
      } 
      
    3. は、例えばのために、ノードサブツリー を管理するために減速して

      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. 使用ノードの減速をNODES_SUCCESSアクションの種類を扱います。あなたがにISNコンポーネントに至るまでいくつかのアクションのクリエイターを渡したいときmapDispatchToProps

      bindActionCreatorsのための唯一のユースケースに関するノード

    5. を取得する

      import { combineReducers } from 'redux'; 
      import opener from './TreeNodeReducer' 
      import nodes from './nodes' 
      
      const rootReducer = combineReducers({ 
          opener, nodes 
      }); 
      
      export default rootReducer; 
      
    6. 使用上記のようmapStateToPropsですReduxを認識しておらず、ReduxストアをディスパッチまたはReduxストアに渡す必要はありません。

      すでにdispatchにアクセスしているので、直接呼び出すことができます。地図を渡すことはその地図の簡略版です。 video

  • +0

    ありがとう、私は決して 'this.props.getFileList();'を呼び出すと思ったことはありませんでした。しかし、なぜ私は 'bindActionCreators'を必要としませんか?私はそれを使用して多くの例を参照し、それらのいくつかは、子ノードにアクションを提供します。 – Mithril

    +0

    ああ、私のコード内の 'getFileList'は' ActionCreater'ではないので、バインドする必要はありません。 – Mithril

    +0

    @ミスリルは答えを更新しました、それを確認してください –

    関連する問題