2016-12-04 26 views
0

首先,我想提一下,我改变两种方法之间唯一的事情是setState vs通过Redux商店。不改变任何东西,即组件等setState的作品,但还原商店更新不

如果我使用setState的方法,我可以关闭我的模式,但如果我通过商店,它不会关闭。任何想法为什么?

这里是我的减速器:

import 'babel-polyfill'; 
import * as types from '../actions/actionTypes'; 

const initialState = { 
    modals: { 
     "modal1": { isDisplayed: true }, 
     "modal2": { isDisplayed: false } 
    } 
}; 

export default (state = initialState, action) => { 

    switch (action.type) { 

     case types.SET_IS_DISPLAYED_MODAL : 
      return Object.assign({}, state, { 
       modals: action.modals 
      }) 

     default: return state 
    } 
    } 
} 

这里是我的onClick行动的两个版本是应该关闭模式。

这是的setState版本,它的工作原理:

displayModal(modalId, value) 
{ 
    let modals = this.props.modals; 
    modals[modalId].isDisplayed = value; 
    return setState({modals: modals}); 
} 

而这里通过了Redux店里发生的版本,它不关我的情态。

displayModal(modalId, value) 
{ 
    let modals = this.props.modals; 
    modals[modalId].isDisplayed = value; 
    return this.props.actions.displayModal(modals); 
} 

没有太多的动作,但在这里它是:

export const displayModal = (modals) => { 
    return { 
     type: types.SET_IS_DISPLAYED_MODAL, 
     modals 
    }; 
} 

只要你看看它的样子在我的部分,那就是:

render() { 

    return(
    <div> 
     <div>Some info...</div> 
     {this.props.modals["modal1"].isDisplayed 
     ? <Modal1 /> 
     : null} 

     {this.props.modals["modal2"].isDisplayed 
     ? <Modal2 /> 
     : null} 
    </div> 
); 
} 

BTW,我知道我正在打击行动和减速器。我也知道,如果我在我的mapStateToProps中放置了一个调试器,我正在为它更新状态。所以我知道行动和减速器都在做他们应该做的事情。

更新: 我只是试了一些东西,这解决了这个问题。我最后一行添加到mapStateToProps并在我的组件更新部分:

function mapStateToProps(state) { 

    return { 
     modals: state.modals, 
     isModal1Displayed: state.modals["modal1"].isDisplayed // Just added this line 
    } 
} 

,并改变了代码,在我的组件:

render() { 

    return(
    <div> 
     <div>Some info...</div> 
     {this.props.isModal1Displayed 
     ? <Modal1 /> 
     : null} 
    </div> 
); 
} 
+0

您可以在连接组件的位置添加代码的一部分吗? – diedu

+0

只需更新原始帖子即可。我没有检查this.props.modals [“modal1”]。isDisplayed,而是在mapStateToProps中为它创建了一个新的道具。我认为它在mapStateToProps中看起来有点时髦,但它工作正常。任何想法为什么最初的代码失败? – Sam

回答

1

首先,从来没有发生变异的终极版减速状态 - 它必须是一个纯函数来正确工作和检测更改。同样的规则适用于你用道具获得的物体。

您必须更改您的代码,以便您只将动作分派给商店并将其降至新的状态。

首先,派遣一个动作:

displayModal(modalId, value) 
{ 
    this.props.actions.displayModal(modalId, value); 
} 

你的行动将携带隐藏或显示其模态信息:

export const displayModal = (modalId, value) => { 
    return { 
     type: types.SET_IS_DISPLAYED_MODAL, 
     modalId, 
     value 
    }; 
} 

然后你就可以减少碳排放量

export default (state = initialState, action) => { 
    switch (action.type) { 
     case types.SET_IS_DISPLAYED_MODAL : 
      return Object.assign({}, state, 
      { 
       modals: Object.assign({}, state.modals, 
       { 
        [action.modalId]: { isDisplayed: action.value } 
       }) 
      }) 

     default: return state 
    } 
} 

由于现在你可以看到这里有很多样板。使用ES6和ES7,您可以使用object spread operator重写您的缩减器,或者您可以使用Immutable.js library,这将帮助您在层次结构中设置更深的属性。

减速与对象传播操作是这样的:

export default (state = initialState, action) => { 
    switch (action.type) { 
     case types.SET_IS_DISPLAYED_MODAL : 
      return { 
       ...state, 
       modals: { 
        ...state.modals, 
        [action.modalId]: { isDisplayed: action.value } 
       } 
      } 

     default: return state 
    } 
} 

你可能会问自己,为什么你的修补程序的工作。让我解释。 当您通过变更modals[modalId].isDisplayed = value中的状态将动作分派给Redux时,可以更改模态。之后,动作被调度,减少并且mapToProps被再次调用。有可能参考检查connect更高阶的组件,并且您已经对modal进行了变异,但不是modals对象,因此它具有相同的引用=您的组件不会重新渲染。通过添加isModal1Displayed字段,实际上会禁用优化,因为存在布尔比较,而不是引用检查,并且组件会重新显示。

我希望它能帮助您理解Redux及其原理。

+0

我其实有点困惑。我理解并同意您回复的第一部分。当我通过redux商店时,我根本不会改变状态 - 就像你在减速器代码中看到的一样。我几次阅读你的回复的第二部分,你谈到了我的修复工作原因,但我无法理解你的观点。唯一的区别是,在我的修复中,我将modal1的isDisplayed值分配给mapStateToProps中的新属性,而不是在组件内部访问其值(this.props.modals [modal1] .isDisplayed)。无论哪种情况,都会从模态对象中检索值。 – Sam

+0

续:事实上,在这两种方法中,我从模态支撑我的价值道具告诉我,我的行动/减速代码工作正常,并成功地更新模态的状态。我只是不知道为什么我无法访问我的组件中使用this.props.modals [modal1] .isDisplayed的modal1 isDisplayed。 – Sam

+1

这很难解释,因为它需要了解Redux内部工作方式,尤其是'connect'组件。你通过执行'modals [modalId] .isDisplayed = value;'来改变'displayModal'中的状态,因为'modals'是一个对象,它仍然指向/引用同一个内存位置。之后,当你的动作被处理时,Redux尝试重新渲染你的组件,但是看到'modals' ==='modals'并且在这种情况下什么都不做。这就是为什么你的组件没有更新。 –