我目前正在尝试使用两个对象对象,其中第二个对象已更新值,并将更新后的值合并到第一个对象中。我写了一个函数来做到这一点,但我无法更新我的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
这里是我传递到函数mapNewStateToOldState
(oldState
,newState
)的物体看起来像。而输出updatedState
看起来像。
这似乎也许这将是一个范围界定问题?但我似乎无法弄清楚发生了什么事。我尝试手动合并它也没有运气。
莫非它是你的新状态有没有在'oldState'中出现的键?无论如何,更有意义的说:'Object.keys(newState).forEach'而不是'Object.keys(oldState).forEach',或者如果你想从'oldState'中移除密钥(如果它们不再存在),那么'[... Object.keys(oldState),... Object.keys(newState)] .forEach',可能转换为'Set'来避免重复的操作。 – trincot
否'newState'将包含我确定存在于'oldState'中的两个键。我附上了开发工具中对象的图像。 我发现奇怪的是,一旦我进入循环Object.keys(oldState).forEach((key)=> {'如果我手动访问这两个对象的键如'oldState [key] .aggSurfMin'和'newState [key] .aggSurfMin'它们输出相同的值,即使在开发工具中它们具有不同的值。 – Frenchy
您的控制台屏幕截图中的componentWillReceiveProps()中的console.log是否与'updatedState ='下的对象相对应?如果是这样,这是因为你没有记录新的状态,你正在记录那些当时没有改变的旧道具,如果可能的话,请更新你的代码,同时记录你的代码'OLD STATE = ','NEW STATE ='和'updatedState =' –