无法在Javascript中为对象分配新值

时间:2017-06-19 05:46:02

标签: javascript json reactjs d3.js ecmascript-6

我目前正在尝试获取两个对象对象,其中第二个对象具有更新值,并将更新后的值合并到第一个对象中。我写了一个函数来做这个,但我无法更新AnimatedDataWrapper中的值。但是,如果我在AnimatedDataWrapper之外运行它可以正常工作..

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 看起来这可能是一个范围问题?但我似乎无法弄清楚发生了什么。我尝试手动合并它也没有运气。

1 个答案:

答案 0 :(得分:2)

好的'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 }