2016-11-09 102 views
0

我是新來的反應+ redux。我遇到了一個問題,當我發送一個動作時,我的應用程序不會重新呈現。但是,我使用getState()來檢查狀態,它確實發生了變化。我查閱文件,但仍然不知道問題是什麼。請幫助我,謝謝。Redux - 該應用程序在調度後不會重新渲染

的代碼是如下

==== actions.js ====

export const ADD_MAIL = 'ADD_MAIL'; 
export const DEL_MAIL = 'DEL_MAIL'; 

export function addMail(email) { 
    return { 
     type: ADD_MAIL, 
     email 
    } 
} 

export function delMail(id) { 
    return { 
     type: DEL_MAIL, 
     id 
    } 
} 

==== reducers.js ====

import { combineReducers } from 'redux' 
import { ADD_MAIL, DEL_MAIL } from '../actions/actions' 
import MAILS from '../data' 

function emails(state = MAILS, action) { 
    switch (action.type) { 
     case ADD_MAIL: 
      console.log("ADD_MAIL"); 

      return [ 
       action.email, 
       ...state 
      ]; 

     case DEL_MAIL: 
      let idx = state.length; 
      let i = 0; 

      // Find the target mail 
      while(idx--) { 
       if (state[idx] && state[idx].serialNo === action.id) 
        i = idx; 
      } 

      let arr1 = state.slice(0, i); 
      let arr2 = state.slice(i + 1); 

      let newList = arr1.concat(arr2); 

      console.log("DEL_MAIL"); 
      return newList; 

     default: 
      return state; 
    } 
} 

const rootReducer = combineReducers({ 
    emails 
}); 

export default rootReducer; 

= === main.js ====

import React from 'react' 
import { render } from 'react-dom' 
import { Link } from 'react-router' 
import { connect } from 'react-redux' 
import { createStore } from 'redux' 
import { addMail, delMail } from './actions/actions' 
import rootReducer from './reducers/reducers' 
import * as btn from './module/button' 
import * as module from './module/module' 


var store = createStore(rootReducer); 

class Inbox extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      searchText: '' 
     } 
     this.handleUserInput = this.handleUserInput.bind(this); 
     this.deleteMail = this.deleteMail.bind(this); 
     this.sendMail = this.sendMail.bind(this); 
    } 

    handleUserInput(searchText) { 
     this.setState({ 
      searchText: searchText 
     }); 
    } 

    deleteMail(obj) { 
     store.dispatch(delMail(obj.serialNo)); 
     console.log(store.getState()); 
     // This displays the correct new state in console after dispatch 
    } 

    sendMail(newMail) { 
     store.dispatch(addMail(newMail)); 
     console.log(store.getState()); 
     // This displays the correct new state in console after dispatch 
    } 

    render() { 
     let mails = []; 
     let search = this.state.searchText.toUpperCase(); 

     let emails = this.props.emails; 
     emails.map(mail => { 
      if (mail.from.toUpperCase().indexOf(search) !== -1) 
       mails.push(mail); 
     }); 

     let sender = (mails.length === emails.length) ? "all" : this.state.searchText; 

     return (
      <div className="main"> 
       <div className="toolbar"> 
        <span>You have {mails.length} message from {sender}.</span> 
        <module.SearchInput searchText={this.state.searchText} onUserInput={this.handleUserInput} />  
        <div className="functions"> 
         <btn.AddButton /> 
        </div> 
       </div> 

       <div className="mailList"> 
        {mails.map(mail => (
         <div className="item" key={mail.serialNo}> 
          <div className="info sender"> 
           From: {mail.from} 
          </div> 
          <div className="info date"> 
           {mail.date} 
          </div> 
          <div className="info subject"> 
           Subject: {mail.subject} 
          </div> 
          <div className="functions"> 
           <btn.ReadButton serialNo={mail.serialNo} /> 
           <btn.DeleteButton serialNo={mail.serialNo} deleteMail={this.deleteMail} /> 
          </div> 
         </div> 
        ))} 
       </div> 

       <module.NewMailInput sendMail={this.sendMail} /> 
      </div> 
     ); 
    } 
} 

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

export default connect(mapStateToProps)(Inbox); 

==== app.js ====

import React from 'react' 
import { render } from 'react-dom' 
import { Router, Route, IndexRoute, browserHistory } from 'react-router' 
import { createStore } from 'redux' 
import { Provider } from 'react-redux' 
import { Menu } from './menu' 
import { Mail } from './main' 
import Inbox from './main' 
import rootReducer from './reducers/reducers' 

var store = createStore(rootReducer); 

class App extends React.Component { 
    constructor(props) { 
     super(props); 
    } 

    render() { 
     return (
      <div style={{height: '100%'}}> 
       <Menu /> 
       {this.props.children} 
      </div> 
     ); 
    } 
} 

class Home extends React.Component { 
    constructor(props) { 
     super(props); 
    } 

    render() { 
     return (
      <Inbox /> 
     ); 
    } 
} 

render(
    <Provider store={store}> 
     <Router history={browserHistory}> 
      <Route path="/" component={App}> 
       <IndexRoute component={Home} /> 
       <Route path="/inbox" component={Inbox} /> 
       <Route path="/message/:mailSerial" component={Mail} /> 
      </Route> 
     </Router> 
    </Provider>, 
document.getElementById('app-container')) 

回答

0

試試這個:

import React from 'react' 
import { render } from 'react-dom' 
import { Link } from 'react-router' 
import { connect } from 'react-redux' 
import { addMail, delMail } from './actions/actions' 
import * as btn from './module/button' 
import * as module from './module/module' 

class Inbox extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     searchText: '' 
    } 
    this.handleUserInput = this.handleUserInput.bind(this); 
    this.deleteMail = this.deleteMail.bind(this); 
    this.sendMail = this.sendMail.bind(this); 
    } 

    handleUserInput(searchText) { 
    this.setState({ 
     searchText: searchText 
    }); 
    } 

    deleteMail(obj) { 
    this.props.delMail(obj.serialNo); //Call the delMail action 
    console.log(store.getState()); 
    } 

    sendMail(newMail) { 
    this.props.addMail(newMail); //Call the addMail action 
    console.log(store.getState()); 
    } 

    render() { 
    let mails = []; 
    let search = this.state.searchText.toUpperCase(); 

    let emails = this.props.emails; 
    emails.map(mail => { 
     if (mail.from.toUpperCase().indexOf(search) !== -1) 
     mails.push(mail); 
    }); 

    let sender = (mails.length === emails.length) ? "all" : this.state.searchText; 

    return (
     <div className="main"> 
     <div className="toolbar"> 
      <span>You have {mails.length} message from {sender}.</span> 
      <module.SearchInput searchText={this.state.searchText} onUserInput={this.handleUserInput} />  
      <div className="functions"> 
      <btn.AddButton /> 
      </div> 
     </div> 

     <div className="mailList"> 
      { 
      mails.map(mail => (
       <div className="item" key={mail.serialNo}> 
        <div className="info sender">From: {mail.from}</div> 
        <div className="info date">{mail.date}</div> 
        <div className="info subject">Subject: {mail.subject}</div> 
        <div className="functions"> 
         <btn.ReadButton serialNo={mail.serialNo} /> 
         <btn.DeleteButton serialNo={mail.serialNo} deleteMail={this.deleteMail} /> 
        </div> 
       </div> 
      )) 
      } 
     </div> 
      <module.NewMailInput sendMail={this.sendMail} /> 
     </div> 
     ); 
    } 
} 

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

//Connect the component to re-render when state change and 
// makes the emails and actions to be available through this.props 
export default connect(mapStateToProps, {delMail, addMail})(Inbox); 



//To connect Mail component which I suppose that is in another file 
function mapStateToProps(state) { 
    return { emails: state.emails }; 
} 
export default connect(mapStateToProps, {})(Mail); 
+0

謝謝你的回答和解釋。 我還有一個問題,如果我有另一個組件郵件,我如何訪問收件箱中的this.props.emails?謝謝。 – Ezek

+0

@Ezek對不起,我不明白,你的意思是我怎樣才能在'Mail'而不是'Inbox'中訪問this.props.emails? –

+0

抱歉說明不清楚。我的意思是我怎樣才能在這兩個組件中共享相同的狀態。例如,在中,我可以使用this.props.emails來訪問電子郵件;在,我怎樣才能使用this.props.emails來訪問電子郵件狀態? – Ezek

0

在你的main.js文件中,你已經創建了一個Inbox組件。這是一個React組件,但不是Redux組件。

在導出收件箱組件時,您必須這樣做。

module.exports = connect((store)=> { 
    return {emails: store.emails} 
})(Inbox) 
+0

抱歉,我犯了一個錯誤。我錯過了main.js代碼的一部分。編輯過它。 – Ezek

0

你有2個店:一個在main.js,一個在app.js。取下一個在main.js和更新呼叫調度使用的一個道具傳遞:

class Inbox extends React.Component { 
    ... 

    deleteMail(obj) { 
     this.props.dispatch(delMail(obj.serialNo)); 
    } 

    ... 
} 
相關問題