2017-01-01 89 views
0

情况 我有一个reactjs应用程序使用REDX。我有一个容器和一个演示组件。我的表示组件呈现一个包含简单文本输入字段数组的表单,并且我将一个'onChange'回调函数从容器传递给表示组件,该表单组件在输入其中一个文本字段时调度动作以更改redux状态。reactjs演示comopnent不重新渲染上REDX状态变化

问题 呈现组件成功地呈现了正确的值从Redux的状态文本字段呈现组件坐骑的时候,但是当我在字段中键入不更新。如果我将容器中传递给演示组件的道具记录在mapStateToProps中,我可以看到onChange函数正确地分派到存储区,并且正在更新redux状态。但是当这种情况发生时,表示组件不会重新呈现,因此在文本字段中输入不会更新视图(键入什么也不做)。

formConnector

import { connect } from 'react-redux' 
    import Form from '../components/Form' 
    import { changeElementValue } from '../actions/actions' 

    const mapStateToProps = (state) => { 
     //e.g. state.elements = [{id:"email", value:"[email protected]"}] 
     let props = { 
      elements: state.elements, 
     } 

     //state and props.elements.{id}.value changes successfully when I 
     //type in one of the input fields, but 
     //the the Form component is not re-rendered 
     console.log(props) 

     return props 
    } 

    const mapDispatchToProps = (dispatch) => { 
     return { 
      onElementChange: (id, value) => { 
       dispatch(changeElementValue(id, value)) 
      }, 
     } 
    } 

    export default connect(mapStateToProps, mapDispatchToProps)(Form) 

表减速

function formReducer(state = initialState, action = null) { 
     switch(action.type) { 
      case types.CHANGE_ELEMENT_VALUE: 
       let newState = Object.assign({}, state) 
       newState.elements[action.id].value = action.value 
       return newState 

      default: 
       return state; 
     } 
    } 

行动

import * as types from './actionTypes' 

    export function changeElementValue(id, value) { 
     return { type: types.CHANGE_ELEMENT_VALUE, id, value } 
    } 
+0

您可以将组件代码和减速?你确定商店改变了吗?它看起来像你正在采取的值设置在state.textField.value,我不知道减速器更改(通过ID,以及它通过什么ID)。我敢打赌,问题出在那个地区 – Kinnza

+0

@Kinnza谢谢你的采访。我有一种可怕的感觉,为了简化这篇文章的代码,我掩盖了这个问题。我的连接器实际上连接了一个呈现一组文本元素的“表单”组件。所以state包含一个id值对的数组。我将用代码重新编写示例来简单地粘贴到此处,但我可以运行以确保它复制问题。与此同时,可以想象我的组件不会识别状态变化,因为它是对状态内的数组中的数值的更改?应该使用不可变的? – xanld

+0

好的,我还没有机会使用我的简化代码构建原型(如果需要,稍后会尝试),但是我已经更新了示例,以便它更真实地表示应用程序中发生的情况。现在有一组元素被渲染。再一次,对于我的预感,你认为表单组件(Form)没有被重新渲染,因为它没有检测到元素数组中某个值更新时状态的变化? – xanld

回答

1

正如评论讨论的,这是由于状态变化。

试图改变你的减速机的代码如下:

case types.CHANGE_ELEMENT_VALUE: { 
    const newElements = state.elements.map(function(el, index) { 
     return action.id === index 
      ? Object.assign({}, el, { value: action.value }) 
      : el; 
    }); 
    return Object.assign({}, state, { elements: newElements); 
} 

或更优雅:

case types.CHANGE_ELEMENT_VALUE: 
    return { ...state, elements: state.elements.map((el, index) => (
     action.id === index ? { ...el, value: action.value } : el 
    )} 
+0

嗨,我标记为答案,因为它确实回答我的问题。其根本问题是返回的状态包含对旧状态的引用,所以没有做出反应没有检测到变化。这个答案帮助我确定了这一点,我非常感谢OB3 Kinnza和Assan。实际上,我弄糟了我的代码示例,我的问题仍然存在,因为我无法直接将解决方案应用到我的实际代码中。所以我在这里的一个新帖子更准确地重新构建了这个问题:http://stackoverflow.com/questions/41418623/change-value-deep-in-redux-state。再次感谢。 – xanld