期望值:单击按钮->更改变量值->重新渲染
发生了什么:单击按钮->错误
我正在寻找最简单的方法来解决此问题。我相信redux可能会有所帮助。
我从yarn create react
创建了项目
import React, { useState } from 'react';
import { VegaLite } from 'react-vega'
var specDefault = {
width: 400,
height: 200,
mark: 'bar',
encoding: {
x: { field: 'a', type: 'ordinal' },
y: { field: 'b', type: 'quantitative' },
},
data: { name: 'table' },
}
const barData = {
table: [
{ a: 'A', b: 28 },
{ a: 'B', b: 55 },
{ a: 'C', b: 43 },
{ a: 'D', b: 91 },
{ a: 'E', b: 81 },
{ a: 'F', b: 53 },
{ a: 'G', b: 19 },
{ a: 'H', b: 87 },
{ a: 'I', b: 52 },
],
}
function UpdateSpec(props) {
const [spec, setSpec] = useState(specDefault);
return (
<div>
<button onClick={() => setSpec(spec.mark = 'line')}>
Change to Line Chart
</button>
<VegaLite spec={spec} data={barData} />
</div>
);
}
function App() {
return (
<>
{UpdateSpec()}
</>
);
}
export default App;
错误:
[Error] TypeError: newSpec is not an Object. (evaluating ''width' in newSpec')
computeSpecChanges (0.chunk.js:65101)
componentDidUpdate (0.chunk.js:64784:101)
commitLifeCycles (0.chunk.js:57118)
commitLayoutEffects (0.chunk.js:60070)
callCallback (0.chunk.js:37600)
dispatchEvent
invokeGuardedCallbackDev (0.chunk.js:37649)
invokeGuardedCallback (0.chunk.js:37702)
commitRootImpl (0.chunk.js:59812)
commitRootImpl
unstable_runWithPriority (0.chunk.js:68183)
commitRoot (0.chunk.js:59654)
finishSyncRender (0.chunk.js:59071)
performSyncWorkOnRoot (0.chunk.js:59057)
performSyncWorkOnRoot
(anonymous function) (0.chunk.js:48541)
unstable_runWithPriority (0.chunk.js:68183)
flushSyncCallbackQueueImpl (0.chunk.js:48536)
flushSyncCallbackQueue (0.chunk.js:48524)
discreteUpdates$1 (0.chunk.js:59160)
discreteUpdates (0.chunk.js:38222)
dispatchDiscreteEvent (0.chunk.js:41621)
dispatchDiscreteEvent
答案 0 :(得分:1)
state
不会合并值,而是会覆盖它们。
与类组件中的
setState
方法不同,useState确实可以 不会自动合并更新对象。您可以复制此 通过将功能更新程序形式与对象传播相结合来实现行为 语法:
您需要在更新时自行合并值。在您的情况下,您只需运行line
就用setSpec(spec.mark = 'line')
替换了整个状态。您可以像下面一样使用functional state update
return (
<div>
<button onClick={() => setSpec(prev => ({...prev, mark:'line'}))}>
Change to Line Chart
</button>
<VegaLite spec={spec} data={barData} />
</div>
);