我复制了ReactTables.js,并一直对其进行修改以显示自己的数据。首先,我将数据放入/variables/general.js文件中,然后将其显示在表中。
下一步是从REST服务获取数据。 我已经编写了用于执行此操作的函数,并首先在Node中甚至是fetch部分中对其进行了测试,现在我试图将它们折叠在React代码中。我知道数据针对dataTable结构的格式正确。
当我从静态数据切换到获取数据并将“ React.useState”放在.then子句下时,我开始收到错误消息:无法在回调内部调用React Hook“ React.useState”。必须在React函数组件或自定义的React Hook函数react-hooks / rules-of-hooks中调用React Hooks。 我尝试将代码放在React.use下,但看起来它想要的是Parms,而不是那里的代码。
这是我的代码,不包括动作和样式。同样,这基本上是他们的即用型代码,只是试图插入获取以获取动态数据。调用getDBLanguagesAndConvertToDataTable时,我需要使用.then。
我做了一些有关钩子的基本阅读,但是迷路了。我应该在另一个地方从REST服务中检索数据吗?
import React from "react";
// @material-ui/core components
import { makeStyles } from "@material-ui/core/styles";
// @material-ui/icons
import Assignment from "@material-ui/icons/Assignment";
import Dvr from "@material-ui/icons/Dvr";
import Favorite from "@material-ui/icons/Favorite";
import Close from "@material-ui/icons/Close";
// core components
import GridContainer from "components/Grid/GridContainer.js";
import GridItem from "components/Grid/GridItem.js";
import Button from "components/CustomButtons/Button.js";
import Card from "components/Card/Card.js";
import CardBody from "components/Card/CardBody.js";
import CardIcon from "components/Card/CardIcon.js";
import CardHeader from "components/Card/CardHeader.js";
import ReactTable from "components/ReactTable/ReactTable.js";
import { dataTable } from "variables/general.js";
import { cardTitle } from "assets/jss/material-dashboard-pro-react.js";
const styles = {
cardIconTitle: {
...cardTitle,
marginTop: "15px",
marginBottom: "0px"
}
};
const useStyles = makeStyles(styles);
function convertMongoLanguagesToDataTable(argDbGetResults) {
//console.log("function convertMongoLanguagesToDataTable")
//console.log("Input:" + JSON.stringify(argDbGetResults))
const dataTable = {
headerRow: ["SourceLanguage", "SourcePhrase", "TargetLanguage", "TargetPhrase", "ID"],
footerRow: ["SourceLanguage", "SourcePhrase", "TargetLanguage", "TargetPhrase", "ID"],
dataRows: []
};
var temporaryMax = argDbGetResults.length
temporaryMax = 3 // get a smaller sample for easier debugging/testing
for (var j = 0; j < argDbGetResults.length; j++) {
var row = argDbGetResults[j]
var strRow = JSON.stringify(row);
//console.log(j, strRow)
var newArray = [row.masterLanguage, row.masterPhrase, row.localizedLanguage, row.localizedPhrase, row._id]
dataTable.dataRows.push(newArray)
}
//console.log("return from function convertMongoLanguagesToDataTable")
//console.log("dataTable:" + JSON.stringify(dataTable))
return dataTable
}
function getDBLanguagesAndConvertToDataTable(fromLanguage, toLanguage) {
// pass the from/to Language on the URL
var url = 'http://localhost:3001/api/gettranslations/' + fromLanguage + "/" + toLanguage
var fetchOptions = {
method: 'GET',
headers: {
'Accept': 'application/json',
}
}
return fetch(url, fetchOptions)
.then(function(data) {
// do something with the data
data.json()
.then (function(fetchResult) {
//console.log("data.json() from Fetch From gettranslation REST service:")
//console.log(JSON.stringify(fetchResult))
var tmpDataTable = convertMongoLanguagesToDataTable(fetchResult)
console.log("return from function convertMongoLanguagesToDataTable")
console.log("PostFetch dataTable:" + JSON.stringify(tmpDataTable))
return tmpDataTable
})
})
.catch(function(err){
console.log("Fetch Error url:" + url)
console.log("Fetch Error:" + err)
throw new Error(err)
})
}
export default function ReactTables() {
var fromLanguage = 'en-US'
var toLanguage = 'es-MX'
getDBLanguagesAndConvertToDataTable(fromLanguage, toLanguage)
.then(function(dataTable) {
console.log("tmpDataTable type=" + typeof dataTable)
var strDataTable = JSON.stringify(dataTable, null, 3);
console.log("Resulting DataTable=")
console.log(strDataTable)
if (dataTable === null || dataTable === undefined) {
console.log('dataTable is null or undefined')
}
if (dataTable.dataRows === null || dataTable.dataRows === undefined) {
console.log('dataTable.dataRows is null or undefined')
}
console.log("Number of dataRows=" + dataTable.dataRows.length)
const [data, setData] = React.useState(
dataTable.dataRows.map((prop, key) => {
return {
ID: key,
SourceLanguage: prop[0],
SourcePhrase: prop[1],
TargetLanguage: prop[2],
TargetPhrase: prop[3],
actions: (
// code omitted
)
};
})
);
const classes = useStyles();
return (
// code omitted
);
}) // end of .then for getting dataTable
}
编辑-第2部分
尝试Marcos回答后的新代码。我必须在地图的末尾注释掉最后的“)”。它可以编译,但是现在出现错误:
Error: Objects are not valid as a React child (found: object with keys {ID, SourceLanguage, SourcePhrase, TargetLanguage, TargetPhrase, actions}). If you meant to render a collection of children, use an array instead.
in ReactTables (created by Context.Consumer)
代码
export default function ReactTables() {
const [data, setData] = React.useState()
React.useEffect(() => {
var fromLanguage = 'en-US'
var toLanguage = 'es-MX'
getDBLanguagesAndConvertToDataTable(fromLanguage, toLanguage)
.then(function(dataTable) {
console.log("tmpDataTable type=" + typeof dataTable)
var strDataTable = JSON.stringify(dataTable, null, 3)
console.log("dataTable=")
console.log(dataTable)
if (dataTable === null || dataTable === undefined) {
console.log('dataTable is null or undefined')
}
if (dataTable.dataRows === null || dataTable.dataRows === undefined) {
console.log('dataTable.dataRows is null or undefined')
}
console.log("Number of dataRows=" + dataTable.dataRows.length)
setData(dataTable)
});
}, [])
return dataTable.dataRows.map((prop, key) => {
return {
ID: key,
SourceLanguage: prop[0],
SourcePhrase: prop[1],
TargetLanguage: prop[2],
TargetPhrase: prop[3],
actions: (
// code omitted
)
};
})
//); -- had to comment this out!
const classes = useStyles();
return (
<GridContainer>
// Code omitted
</GridContainer>
);
}
答案 0 :(得分:2)
只能在渲染函数上调用钩子,如果使用钩子,则必须始终调用钩子,并且始终以相同的顺序进行调用。
您在useState
的回调中使用Promise
。取而代之的是,您必须在组件上使用它,并使用useEffect
来调用数据提取逻辑并根据结果设置状态。
如果需要操纵数据以显示它,则可以使用useMemo
从原始数据中获取已处理的数据,并且仅在数据更改时执行此操作。确保从状态中设置的data
获取数据。
最后,由于useEffect
将在初始渲染后运行,因为正在检索数据或发生错误,因此数据不一定可用。您可以通过条件返回来处理此问题,只需确保将所有挂钩都放置在条件返回之前,因为如前所述,您不能在渲染之间修改对任何挂钩的任何调用。
export default function ReactTables() {
const [data, setData] = React.useState()
React.useEffect(() => {
getDBLanguagesAndConvertToDataTable()
.then(result => {
setData(result)
});
}, [])
const processedData = React.useMemo(() => data && data.dataRows.map((prop, key) => {
return {
ID: key,
SourceLanguage: prop[0],
SourcePhrase: prop[1],
TargetLanguage: prop[2],
TargetPhrase: prop[3],
actions: (
// code omitted
)
};
}), [data])
const classes = useStyles()
if (!processedData) {
return null // Use a loading component if you prefer
}
return (
<GridContainer>
// Code omitted
</GridContainer>
);
}
答案 1 :(得分:2)
Ciao,React.useState
用于定义状态变量,必须在组件主体中使用。像这样:
export default function ReactTables(){
const [data, setData] = React.useState([]) // [] this is the initial value for data
...
}
然后,在.then
回调中,您可以通过调用setData(/*data from fetch*/)
来设置此状态。
PART 2
假设dataTable.dataRows
是一个数组,我认为您的问题出在map
函数中,尤其是在actions
中。您无法返回类似actions: (...)
之类的内容,因为JSON对象中不允许使用圆括号。如果actions
是一个数组,请将actions: (...)
替换为actions: [...]
。如果actions
是对象,则将actions: (...)
替换为actions: {...}