2017-06-19 189 views
0

我目前正在尝试使用两个对象对象,其中第二个对象已更新值,并将更新后的值合并到第一个对象中。我写了一个函数来做到这一点,但我无法更新我的AnimatedDataWrapper中的值。但是,如果我运行它AnimatedDataWrapper之外,它工作正常..无法将新值分配给Javascript中的对象

import React, { Component } from 'react' 
import PropTypes from 'prop-types' 
import * as d3 from 'd3' 

const mapNewStateToOldState = (oldState, newState) => { 
    Object.keys(oldState).forEach((key) => { 
    Object.assign(oldState[key], newState[key]) 
    }) 
    return oldState 
} 

// const mapNewStateToOldState = (oldState, newState) => 
// Object.keys(oldState).map(key => Object.assign(oldState[key], newState[key])) 

const obj = { 0: { data: 1 } } 
const newObj = { 0: { data: 2 } } 

console.log(mapNewStateToOldState(obj, newObj)) // THIS WORKS 
console.log(obj) // THIS WORKS 

const AnimatedDataWrapper = (dataProp, transitionDuration = 300) => ComposedComponent => 
    class extends Component { 
    constructor(props) { 
     super(props) 
     const data = this.props[dataProp] 
     this.state = Object.keys(data) 
     .map(label => ({ [label]: data[label] })) 
     .reduce((prev, curr) => ({ ...prev, ...curr }), {}) 
    } 

    componentWillReceiveProps(nextProps) { 
     const data = this.props[dataProp] 
     console.log(data) 
     const nextData = nextProps[dataProp] 
     const dataKeys = this.props.dataKeys 
     const dataUnchanged = Object.keys(data) 
     .map(label => data[label] === nextData[label]) 
     .reduce((prev, curr) => prev && curr) 
     if (dataUnchanged) { 
     return 
     } 
     d3.select(this).transition().tween('attr.scale', null) 
     d3 
     .select(this) 
     .transition() 
     .duration(transitionDuration) 
     .ease(d3.easeLinear) 
     .tween('attr.scale',() => { 
      const barInterpolators = data.map((...args) => { 
      const index = args[1] 
      return dataKeys.map((key) => { 
       const interpolator = d3.interpolateNumber(
       this.state[index][key], 
       nextData[index][key], 
      ) 
       return { key, interpolator } 
      }) 
      }) 
      return (t) => { 
      const newState = barInterpolators 
       .map(bar => 
       bar 
        .map(({ key, interpolator }) => ({ [key]: interpolator(t) })) 
        .reduce((result, currentObject) => { 
        Object.keys(currentObject).map((key) => { 
         if (Object.prototype.hasOwnProperty.call(currentObject, key)) { 
         result[key] = currentObject[key] 
         } 
         return null 
        }) 
        return result 
        }, {}), 
      ) 
       .reduce((newObject, value, index) => { 
       newObject[index] = value 
       return newObject 
       }, {}) 
      const oldState = this.state 
      console.log(`OLD STATE = ${JSON.stringify(oldState)}`) 
      console.log(`NEW STATE = ${JSON.stringify(newState)}`) 
      const updatedState = mapNewStateToOldState(oldState, newState) // THIS DOES NOT WORK 
      console.log(`UPDATED STATE = ${JSON.stringify(updatedState)}`) 
      this.setState(updatedState) 
      } 
     }) 
    } 

    render() { 
     const { props, state } = this 
     const newData = Object.keys(state).map(val => state[val]) 
     const newDataProps = { ...{ data: newData } } 
     const newProps = { ...props, ...newDataProps } 
     return <ComposedComponent {...newProps} /> 
    } 
    } 

AnimatedDataWrapper.PropType = { 
    dataProp: PropTypes.string.isRequired, 
    transitionDuration: PropTypes.number, 
    dataKeys: PropTypes.instanceOf(Array).isRequired, 
    maxSurf: PropTypes.number.isRequired, 
} 

export default AnimatedDataWrapper 

这里是我传递到函数mapNewStateToOldStateoldStatenewState)的物体看起来像。而输出updatedState看起来像。

enter image description here 这似乎也许这将是一个范围界定问题?但我似乎无法弄清楚发生了什么事。我尝试手动合并它也没有运气。

+0

莫非它是你的新状态有没有在'oldState'中出现的键?无论如何,更有意义的说:'Object.keys(newState).forEach'而不是'Object.keys(oldState).forEach',或者如果你想从'oldState'中移除密钥(如果它们不再存在),那么'[... Object.keys(oldState),... Object.keys(newState)] .forEach',可能转换为'Set'来避免重复的操作。 – trincot

+0

否'newState'将包含我确定存在于'oldState'中的两个键。我附上了开发工具中对象的图像。 我发现奇怪的是,一旦我进入循环Object.keys(oldState).forEach((key)=> {'如果我手动访问这两个对象的键如'oldState [key] .aggSurfMin'和'newState [key] .aggSurfMin'它们输出相同的值,即使在开发工具中它们具有不同的值。 – Frenchy

+1

您的控制台屏幕截图中的componentWillReceiveProps()中的console.log是否与'updatedState ='下的对象相对应?如果是这样,这是因为你没有记录新的状态,你正在记录那些当时没有改变的旧道具,如果可能的话,请更新你的代码,同时记录你的代码'OLD STATE = ','NEW STATE ='和'updatedState =' –

回答

1

好醇” Object.assign会做你要找的,在前面的物体会被其他人使用相同的按键遵循覆盖工作:

var oldState = {a: 1, b: 2} 
var newState = {b: 3, c: 4} 
Object.assign(oldState, newState) === { a: 1, b: 3, c: 4 } 

stage-3 ecmascript you can use the spread syntax

var oldState = {a: 1, b: 2} 
var newState = {b: 3, c: 4} 
{ ...oldState, ...newState } === { a: 1, b: 3, c: 4 } 
+1

感谢您的答复。我实际上已经在这里使用Object.assign const mapNewStateToOldState =(oldState,newState)=> Object.keys(oldState).forEach((key)=> ObjectState(oldState [key],newState [键]) }) return oldState }' 但由于某种原因,当我在这里调用'const updatedState = mapNewStateToOldState(oldState,newState)'它不起作用。 – Frenchy

+1

Object.assign返回一个新的对象。因此,在'mapNewStateToOldState'的每个循环中,一个新的对象没有被分配给任何变量,因此它正在丢失。然后,当你返回旧状态,你真的只是返回以前的版本 –

+1

在你的代码中的这条线:'const updatedState = Object.assign(oldState,newState)' –

相关问题