所以我有这个 JSX 元素,我试图在 Class 组件中呈现。它本质上是 D3 的 React 库提供的视觉效果。但是,我在尝试渲染 D3 视觉对象时收到此错误:
Unhandled Rejection (Error): Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
以下是发生错误的一些相关代码片段:
将所有必要的道具传递给 D3 库的构建器函数
const buildModelVisual = (dataPoints) => {
console.log("category: " + dataPoints[0].category)
console.log("range: " + dataPoints[0].range)
console.log("frequency: " + dataPoints[0].frequency)
dataPoints[0].frequency.forEach(f =>
console.log("f: " + f)
)
const width = 960,
height = 500,
margins = {top: 50, right: 50, bottom: 50, left: 50},
id = "model-visual",
title = "NaiveBayes Model Visual",
svgClassName = "model-visual-class",
titleClassName = "model-visual-title-class",
legendClassName = "model-legend",
showLegend = true,
showXAxis = true,
showYAxis = true,
showXGrid = false,
showYGrid = false,
ranges = [
...dataPoints[0].range
],
frequencies = [
...dataPoints[0].frequency
],
x = () => {
return ranges.forEach(r => {
return r;
})
},
xOrient = 'bottom',
xTickOrient = 'bottom'
const xDomain = dataPoints[0].range.forEach(r => {
return {
category: dataPoints[0].category, range: r
}
}),
xRangeRoundBands = {interval: [0, width - margins.left - margins.right], padding: 0.1},
xScale = 'ordinal',
xAxisClassName = 'x-axis',
xLabel = dataPoints[0].category,
xLabelPosition = 'bottom',
xTickPadding = 3,
xInnerTickSize = 6,
xOuterTickSize = 6,
y = () => {
return frequencies.forEach(freqInRange => {
return freqInRange.forEach(f => {
return f;
});
})
},
yOrient = 'left',
yTickOrient = 'left',
yRange = [height - margins.top - margins.bottom, 0]
const yDomain = [0, d3.max(
dataPoints[0].frequency,
(f) => {
return f.value
}
)],
yScale = 'linear',
yAxisClassName = 'y-axis',
yLabel = "Population",
yTickFormat = d3.format(".2s"),
yLabelPosition = 'left',
yTickPadding = 4,
yInnerTickSize = 6,
yOuterTickSize = 6
return (
<Chart
title={title}
id={id}
width={width}
height={height}
>
<BarStackChart
title= {title}
data= {ranges}
width= {width}
height= {height}
id= {id}
margins= {margins}
svgClassName= {svgClassName}
titleClassName= {titleClassName}
yAxisClassName= {yAxisClassName}
xAxisClassName= {xAxisClassName}
legendClassName= {legendClassName}
categoricalColors= {d3.scaleOrdinal(d3.schemeCategory10)}
chartSeries = {ranges}
showLegend= {showLegend}
showXAxis= {showXAxis}
showYAxis= {showYAxis}
x= {x}
showXGrid= {showXGrid}
xDomain= {xDomain}
xRangeRoundBands= {xRangeRoundBands}
xScale= {xScale}
xOrient= {xOrient}
xTickOrient= {xTickOrient}
xTickPadding = {xTickPadding}
xInnerTickSize = {xInnerTickSize}
xOuterTickSize = {xOuterTickSize}
xLabel = {xLabel}
xLabelPosition = {xLabelPosition}
y= {y}
showYGrid= {showYGrid}
yOrient= {yOrient}
yRange= {yRange}
yDomain= {yDomain}
yScale= {yScale}
yTickOrient= {yTickOrient}
yTickPadding = {yTickPadding}
yInnerTickSize = {yInnerTickSize}
yOuterTickSize = {yOuterTickSize}
yTickFormat= {yTickFormat}
yLabel = {yLabel}
yLabelPosition = {yLabelPosition}
/>
</Chart>
)
}
渲染图形和界面的 HO 类组件
constructor(props) {
super(props);
this.ref = React.createRef();
this.state = {
input: "",
output: [],
visual: null
}
}
为 BarStackChart 设置数据的 REST API 调用(在默认类 Component 中)
callGetModel = () => {
let getModelRanges = getCall(ApiURL.get_model_ranges);
let getModelFrequencies = getCall(ApiURL.get_model_frequencies);
Promise.all([getModelRanges, getModelFrequencies]).then(data => {
this.setState({output: data})
const dataPoints = [];
for (let value in JSON.parse(data[0].toString())) {
dataPoints.push({
category: value,
range: JSON.parse(data[0].toString())[value],
frequency: JSON.parse(data[1].toString())[value]
})
}
console.log(dataPoints)
const ModelVisual = buildModelVisual(dataPoints)
this.setState({ visual: ModelVisual }) // returns JSX element
console.log(this.state.visual)
});
}
类 Component 的渲染方法
render() {
return <div>
<h3>Welcome to Naive Bayes Java!</h3>
<p>The REST API for this project is hosted at</p>
<a style={{'display':'block', 'paddingBottom':'1.5em', 'color':'rgb(0, 150, 196)'}} href="https://naivebayesjava.herokuapp.com/swagger-ui.html#/">https://naivebayesjava.herokuapp.com/</a>
<button style={{'display':'inline', 'background':'rgb(32, 32, 32)', 'color':'rgb(190, 190, 190)'}} onClick={this.callListOfFiles}>
Get List of Valid Files
</button>
<button style={{'background':'rgb(32, 32, 32)', 'color':'rgb(190, 190, 190)'}} onClick={this.callGetModel}>
Get Model
</button>
<button style={{'background':'rgb(32, 32, 32)', 'color':'rgb(190, 190, 190)'}} onClick={this.callGetModelAccuracy}>
Get Model Accuracy
</button>
<div style={{'margin':'auto', 'display':'block'}}>
<input style={{'background':'rgb(32, 32, 32)', 'color':'rgb(190, 190, 190)'}} type='text' value={this.state.input} onChange={this.handleChange}/>
<button style={{'background':'rgb(32, 32, 32)', 'color':'rgb(190, 190, 190)'}} onClick={this.callSetData}>
Set Training Data File
</button>
</div>
{/* <button onClick={this.callGetTrainingData}>
Get Training Data Arff Files
</button> */}
<div style={{'padding-top':'0.5em'}} ref={this.ref}></div>
<output type='textBox' style={{ 'padding':'1.25em', 'display':'block', 'Height': '30px', 'Width': '300px' }}>
{ Object.keys(this.state.output).map(key => {
return this.state.output[key]
}) }
</output>
{ this.state.visual }
</div>
}
除了设置“this.state.visual”JSX 元素并在渲染方法中调用它之外,肯定有更好的方法来实现这一点,尽管我对 React(大约一个月前开始学习)和 JS(大约 3 个月前开始)我不太了解两者的所有常见做法;只是它们如何工作的一般理论。
这个界面和我的作品集托管在joshuabaroni.github.io。我试图改进的界面是“项目”部分下的 NaiveBayes 项目界面
任何建议将不胜感激!整个 JS 文件可根据要求提供。