无法为 React 功能组件设置状态
Failed to set state for react functional component
预期结果:单击按钮 -> 更改变量值 -> 重新呈现
发生了什么:单击了按钮 -> 错误
我正在寻找解决此问题的最直接方法。我相信 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 (0.chunk.js:59160)
discreteUpdates (0.chunk.js:38222)
dispatchDiscreteEvent (0.chunk.js:41621)
dispatchDiscreteEvent
state
使用挂钩更新不会合并值,而只是覆盖它们。
Unlike the setState
method found in class components, useState does
not automatically merge update objects. You can replicate this
behavior by combining the function updater form with object spread
syntax:
您需要在更新时自行合并值。在您的情况下,您只是用 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>
);
预期结果:单击按钮 -> 更改变量值 -> 重新呈现
发生了什么:单击了按钮 -> 错误
我正在寻找解决此问题的最直接方法。我相信 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 (0.chunk.js:59160)
discreteUpdates (0.chunk.js:38222)
dispatchDiscreteEvent (0.chunk.js:41621)
dispatchDiscreteEvent
state
使用挂钩更新不会合并值,而只是覆盖它们。
Unlike the
setState
method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:
您需要在更新时自行合并值。在您的情况下,您只是用 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>
);